Intereting Posts
вызов bash с опцией -t Являются ли FIFO, pipe & Unix доменными сокетами одинаковыми в ядре Linux? Лучший способ использования checkinstall Зачем использовать Kali Linux вместо «Ubuntu с Kali Tools»? как использовать регулярное выражение в псевдониме? Linux: удалить файл * .. но не file1 и file2 Инструмент Diff с хорошим выходом, например kdiff3 Операция `с эхом при попытке awk Разделить файлы на основе поиска шаблонов. Разделить имя файла с помощью шаблона, который мы искали переменное расширение в подстановке команд над SSH bash 4.X Как я могу использовать вложенные для замены if-then-fi? ("[: -f: ожидаемый двоичный оператор") Проблемы с установкой R на Red Hat 6, требует libjpeg.so.62 Есть ли разница между опцией монтирования FUSE «uid» и специфичной для bindfs опцией «force-user»? Как вызвать предыдущую команду (без выполнения), чтобы ее изменить? Определение конкретного процессора, на котором запущен процесс

Как вести историю команд с временными отметками, выводимыми на терминал непрерывно?

Я использую простой псевдоним, чтобы включить «отслеживание» команд в одном или нескольких терминальных окнах:

alias trackmi='export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"' 

Затем я просто tail -f мой файл .bash_history в другом терминале в рабочей области, чтобы получить немедленную обратную связь. Я только что включил неограниченную историю и обновил свой исторический формат ( export HISTTIMEFORMAT="[%F %T] " ) в .bashrc . Конечно, команда history отображает метки времени. Но формат файла истории сам по себе:

 #1401234303 alias #1401234486 cat ../.bashrc 

Как я могу преобразовать время Unix и всю команду, отображаемую в одной строке, точно так же, как с помощью команды history , включая нумерацию:

 578 [2014-05-27 19:45:03] alias 579 [2014-05-27 19:48:06] cat ../.bashrc 

… и следовать этому. Или найти способ непрерывного вывода вывода команды history на терминал?

С GNU awk :

 tail -fn+1 ~/.bash_history | awk ' /^#/{printf "%-4d [%s] ", ++n, strftime("%F %T", substr($0, 2)); next}; 1' 

Вот конечный продукт в действии на разном экране xterm, начиная с стандартных по умолчанию параметров оболочки и заканчивая работой всего за пару команд:

введите описание изображения здесь

Более грубый способ сделать это, чем продемонстрировать на скриншоте, может выглядеть так:

 PS1='$( { date ; fc -l -0 ; } >${TGT_PTY} )'$PS1 

Где ${TGT_PTY} будет тем, что вы выберете из команды tty когда на самом деле запускаете интерактивную оболочку на экране, где вы хотите свой выход. Или, действительно, вы могли бы использовать любой записываемый файл вообще, поскольку он по сути является только целью перенаправления файлов.

Я использую синтаксис pty для псевдотерминала, потому что я предполагаю, что это какой-то xterm, но вы можете легко выделить vt – и ваша потоковая история всегда будет только CTRL-ALT-Fn клавиш CTRL-ALT-Fn . Если бы это был я, я мог бы объединить два понятия и сделать его сеансом screen или tmux на выделенном vt … Но я отвлекся.

На недавно загруженной машине меня приветствует типичное приглашение /bin/login на типичной консоли getty Linux. Я kmscon CTRL-ALT-F2 для доступа к менее типичной консоли kmscon которая ведет себя намного больше, чем xterm чем tty . Я вхожу в команду tty и получаю в ответ /dev/pts/0 .

Обычно xterms мультиплексирует одно терминальное устройство на несколько с использованием псевдотерминалов, поэтому, если вы хотите сделать аналогичную вещь в X11 путем переключения между вкладками терминала или окнами, вы, вероятно, получите вывод, например, /dev/pts/[0-9]* также. Но виртуальные терминальные консоли, к которым доступны CTRL-ALT-Fn клавиш CTRL-ALT-Fn являются истинными (er) терминальными устройствами и поэтому получают свое собственное /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> для каждой команды, <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 могут быть представлены всевозможные варианты форматирования, некоторые из которых применяются к отметкам времени. И, конечно, как вы заметили выше, 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 

В качестве альтернативы, используя команду history bash , вы можете определить функцию _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} 

Не стесняйтесь играть с форматированием, но это (я считаю) делает то, о чем вы просите … сохраняйте где-нибудь в своем PATH, исполняйте и наслаждайтесь:

 #!/bin/bash count=$( echo "scale=0 ; $(cat ~/.bash_history | wc -l ) / 2" | bc -l ) tail -f ~/.bash_history | awk -vc=$count '{if($1 ~/^#/){gsub(/#/, "", $1);printf "%s\t", c; "date \"+%F %T\" --date @" $1 | getline stamp; printf "[%s]\t",stamp;c++}else{print $0}}' 

Я уверен, что его можно оптимизировать, но вы получите эту идею.

Краткое объяснение: поскольку ~ / .bash_history не отслеживает счет, мы сначала определяем количество записей. Затем немного магии awk, чтобы правильно форматировать и отслеживать количество записей.