Вот конечный продукт в действии на xterm с разделенным экраном, по умолчанию оболочка по умолчанию работает всего за пару команд:
Более грубый способ сделать это, чем показано на скриншоте, может выглядеть так:
PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1
Где ${TGT_PTY}
бы вы ни находились в tty
команде, когда запускаете интерактивную оболочку на экране, где вы хотите получить вывод. Или, на самом деле, вы можете использовать любой доступный для записи файл, так как он по сути является целью перенаправления файлов.
Я использую синтаксис pty для псевдотерминала, потому что я предполагаю, что это какой-то xterm, но вы могли бы так же легко выделить vt - и ваша потоковая история всегда является лишь CTRL-ALT-Fn
ключевой комбинацией. Если бы это был я, я мог бы объединить два понятия и сделать это сеансом screen
или tmux
сеансом на выделенном виртуальном пути ... Но я отвлекся.
На недавно загруженной машине меня приветствует типичная /bin/login
подсказка на типичной getty
консоли Linux . Я нажимаю, CTRL-ALT-F2
чтобы получить доступ к менее типичной kmscon
консоли, которая ведет себя намного больше, xterm
чем a tty
. Я ввожу команду tty
и получаю в ответ /dev/pts/0
.
Как правило, xterms мультиплексирует одно оконечное устройство на несколько, используя псевдотерминалы - поэтому, если бы вы делали подобное в X11, переключаясь между вкладками клемм или окнами, вы, вероятно, также получили бы вывод /dev/pts/[0-9]*
. Но виртуальные терминальные консоли, к которым CTRL-ALT-Fn
получают доступ с помощью комбинаций клавиш, являются истинными (эр) терминальными устройствами и поэтому получают свое собственное /dev/tty[0-9]*
обозначение.
Вот почему после входа в консоль 2, когда я печатаю tty
в командной строке, ответ, /dev/pts/0
но когда я делаю то же самое в консоли 1, вывод /dev/tty1
. В любом случае обратно на консоль 2 я потом делаю:
bash
PS1='$( { date ; fc -l -0 ; } >/dev/tty1 )'$PS1
Там нет заметного эффекта. Я продолжаю набирать еще несколько команд, а затем переключаюсь на консоль 1, CTRL-ALT-F1
снова нажимая . И там я нахожу повторяющиеся записи, которые похожи <date_time>\n<hist#>\t<hist_cmd_string>
на каждую команду, которую я набрал на консоли 2.
Если запретить прямую запись на терминальное устройство, другой вариант может выглядеть примерно так:
TGT_PTY=
mkfifo ${TGT_PTY:=/tmp/shell.history.pipe}
{ echo 'OPENED ON:'
date
} >${TGT_PTY}
И тогда, может быть ...
less +F ${TGT_PTY}
Команда грубого приглашения не соответствует вашим спецификациям - для нее нет ни строки date
форматирования, ни параметров форматирования fc
- но ее механизм не требует много: каждый раз, когда ваш запрос отображает последнюю команду истории, а текущая дата и время записываются в ${TGT_PTY}
файл , который вы укажете. Это так просто.
Просмотр и распечатка истории оболочки является fc
основной целью. Это встроенная оболочка, даже если date
нет. Он zsh
fc
может предоставить все возможные варианты форматирования, некоторые из которых применяются к временным меткам. И, конечно же , как Вы отмечаете выше, bash
«s history
может сделать то же самое.
В целях более чистого вывода вы можете использовать метод, который я лучше объяснил здесь, чтобы установить постоянную переменную отслеживания в текущей оболочке, несмотря на необходимость отслеживать ее и обрабатывать ее в подоболочках в последовательности подсказок.
Вот портативное средство форматирования в соответствии с вашими требованиями:
_HIST() { [ -z ${_LH#$1} ] ||
{ date "+${1}%t[%F %T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
: "${_LH=0}"
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Я реализую счетчик last_history,$_LH
который просто отслеживает последние обновления, чтобы вы не выписывали одну и ту же команду истории дважды - например, только для нажатия клавиши enter. Необходимо немного поспорить, чтобы увеличить переменную в текущей оболочке, чтобы она сохраняла свое значение, даже если функция вызывается в подоболочке - что, опять же, лучше объяснено в ссылке .
Его вывод выглядит как <hist#>\t[%F %T]\t<hist_cmd>\n
Но это только полностью портативная версия. С bash
этим можно справиться с меньшими затратами и реализовать только встроенные функции оболочки - что, вероятно, желательно, если учесть, что эта команда будет запускаться при каждом нажатии [ENTER]
. Вот два способа:
_HIST() { [ -z ${_LH#$1} ] || {
printf "${1}\t[%(%F %T)T]"
fc -nl -0
} >${TGT_PTY}
printf "(_LH=$1)-$1"
}
PROMPT_COMMAND=': ${_LH=0};'$PROMPT_COMMAND
PS1='${_LH##*[$(($(_HIST \!)))-9]}'$PS1
Кроме того, используя команду bash
's history
, вы можете определить _HIST
функцию следующим образом:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
Вывод для любого метода также выглядит следующим образом: <hist#>\t[%F %T]\t<hist_cmd>\n
хотя history
метод включает в себя несколько ведущих пробелов. Тем не менее, я полагаю, что history
временные метки метода будут более точными, так как я не думаю, что им нужно будет ждать завершения указанной команды, прежде чем получить их штамп.
Вы можете избежать отслеживания любого состояния в обоих случаях, если только вы каким-то образом фильтруете поток uniq
- как вы могли бы сделать, mkfifo
как я упоминал ранее.
Но выполнение этого в приглашении, как это, означает, что оно всегда обновляется только тогда, когда это необходимо, простым действием обновления приглашения. Это просто.
Вы также можете сделать что-то похожее на то, что вы делаете, tail
но скорее установить
HISTFILE=${TGT_PTY}
fn+1
чтобы сравнить! Спасибо!