Com o GNU awk :
tail -fn+1 ~/.bash_history | awk '
/^#/{printf "%-4d [%s] ", ++n, strftime("%F %T", substr($0, 2)); next}; 1'
Eu uso um simples alias para ativar o "rastreamento" de comandos em uma ou várias janelas de terminal:
alias trackmi='export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"'
Então eu só tail -f meu arquivo .bash_history em outro terminal no espaço de trabalho para obter feedback imediato. Acabei de ativar o histórico ilimitado e atualizei meu formato de histórico ( export HISTTIMEFORMAT="[%F %T] " ) em .bashrc . É claro que o comando history exibe os registros de data e hora. Mas o formato do arquivo de histórico é:
#1401234303
alias
#1401234486
cat ../.bashrc
Como posso ter o tempo do Unix convertido e todo o comando exibido em uma única linha como no comando history , incluindo numeração:
578 [2014-05-27 19:45:03] alias
579 [2014-05-27 19:48:06] cat ../.bashrc
... e siga isso. Ou encontrar uma maneira de gerar continuamente a saída do comando history para o terminal?
Aqui está o produto final em ação em um xterm de tela dividida, basicamente de padrões de shell, para trabalhar em apenas alguns comandos:

Umamaneiramaisdifícildefazerissodoqueédemonstradonacapturadetelapodeserassim:
PS1='$({date;fc-l-0;}>${TGT_PTY})'$PS1Onde${TGT_PTY}seriaoquevocêreceberdocomandottyquandoestiverexecutandoumshellinterativonatelaondedesejasuasaída.Ou,naverdade,vocêpoderiausarqualquerarquivogravável,poiséessencialmenteapenasumalvoparaoredirecionamentodearquivos.
Euusoasintaxeptyparapseudo-terminalporqueestouassumindoqueéumxtermdealgumtipo,masvocêpodefacilmentededicarumvt-eseustreamedohistóricoésempreapenasumacombinaçãode%CTRL-ALT-Fn.Sefosseeu,eupoderiacombinarasduasnoçõesetorná-loumasessãoscreenoutmuxemumvtdedicado...Maseudiscordo.
Emumamáquinarecém-inicializada,sourecebidocomoprompttípico/bin/loginemumconsoletípicodoLinuxgetty.EupressionoCTRL-ALT-F2paraacessarumconsolekmsconmenostípicoquesecomportamuitomaiscomoxtermdoquetty.Euinsiroocomandottyereceboemresposta/dev/pts/0.
Geralmentextermsmultiplexamumúnicoterminalemmúltiplosusandopseudo-terminais-entãosevocêfizessealgosimilarnoX11trocandoentreasabasoujanelasdoterminal,vocêprovavelmentereceberiaumasaídacomo/dev/pts/[0-9]*também.MasosconsolesdeterminalvirtuaisacessadoscomcombinaçõesdeteclasCTRL-ALT-Fnsãodispositivosdeterminaltrue(er)e,portanto,recebemsuaprópriadesignação/dev/tty[0-9]*.
Éporissoquedepoisdeefetuarloginnoconsole2quandodigitottynoprompt,arespostaé/dev/pts/0,masquandoeufaçoomesmonoconsole1,asaídaé/dev/tty1.Dequalquerforma,devoltaaoconsole2eufaço:
bashPS1='$({date;fc-l-0;}>/dev/tty1)'$PS1Nãoháefeitodiscernível.Eucontinuodigitandomaisalgunscomandosedepoismudoparaoconsole1pressionandoCTRL-ALT-F1novamente.Eláeuencontroentradasrepetidasqueparecemcom<date_time>\n<hist#>\t<hist_cmd_string>paracadacomandoqueeudigiteinoconsole2.
Noentanto,impedindoagravaçãodiretaemumdispositivodeterminal,outraopçãopoderiaseralgocomo:
TGT_PTY=mkfifo${TGT_PTY:=/tmp/shell.history.pipe}{echo'OPENEDON:'date}>${TGT_PTY}Eentãotalvez...
less+F${TGT_PTY}Ocomandopromptbrutonãoatendeàssuasespecificações-nenhumastringdeformatoparadateenenhumaopçãodeformataçãoparafc-,masseumecanismonãoexigemuito:todavezqueseupromptrenderizaroúltimocomandohistóricoeadataehoraatuaissãogravadasnoarquivo${TGT_PTY}quevocêespecificar.Étãosimplesassim.
Assistireimprimirohistóricodoshelléoobjetivoprincipaldefc.Éumshellembutido,mesmoquedatenãoseja.Emzshfcpodefornecertodosostiposdeopçõesdeformataçãoextravagantes,váriasdasquaisseaplicamacarimbosdedata/hora.E,claro,comovocêobservouacima,bash'historypodefazeromesmo.
Nointeressedaproduçãomaislimpa,vocêpodeusarumatécnicaqueexpliqueimelhor
Aqui está um meio portátil de formatação de acordo com suas especificações:
_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
Eu implemento o contador last_history $_LH que apenas rastreia as últimas atualizações para que você não escreva o mesmo comando history duas vezes - por exemplo, apenas pressionando enter. Há um pouco de discussão necessária para obter a variável incrementada no shell atual, de modo que ela retenha seu valor mesmo que a função seja chamada em um subshell - o que é, novamente, melhor explicado no link .
Sua saída parece com <hist#>\t[%F %T]\t<hist_cmd>\n
Mas essa é apenas a versão totalmente portátil. Com bash , isso pode ser feito com menos e implementando apenas builtins de shell - o que é provavelmente desejável quando você considera que este é um comando que será executado toda vez que você pressionar [ENTER] . Aqui estão duas maneiras:
_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
Como alternativa, usando o comando bash ' history , você pode definir a função _HIST desta maneira:
_HIST() { [ -z ${_LH#$1} ] ||
HISTTIMEFORMAT="[%F %T]<tab>" \
history 1 >${TGT_PTY}
printf "(_LH=$1)-$1"
}
A saída de qualquer método também se parece com: <hist#>\t[%F %T]\t<hist_cmd>\n , embora o método history inclua alguns espaços em branco iniciais. Ainda assim, acredito que os timestamps do método history serão mais precisos, pois não acredito que precisem esperar que o comando referenciado seja concluído antes de adquirir seu selo.
Você pode evitar o rastreamento de qualquer estado em ambos os casos se, de alguma forma, você filtrar o fluxo com uniq , como faria com mkfifo , como mencionei antes.
Mas fazê-lo no prompt desse jeito significa que ele sempre é atualizado assim que necessário, apenas pela simples ação de atualizar o prompt. É simples.
Você também pode fazer algo semelhante ao que está fazendo com tail , mas definir
HISTFILE=${TGT_PTY}
Sinta-se à vontade para jogar com a formatação, mas isso (eu acredito) faz o que você está pedindo ... salve em algum lugar no seu PATH, torne executável e aproveite:
#!/bin/bash
count=$( echo "scale=0 ; $(cat ~/.bash_history | wc -l ) / 2" | bc -l )
tail -f ~/.bash_history | awk -v c=$count '{if($1 ~/^#/){gsub(/#/, "", $1);printf "%s\t", c; "date \"+%F %T\" --date @" $1 | getline stamp; printf "[%s]\t",stamp;c++}else{print $0}}'
Tenho certeza de que pode ser otimizado, mas você tem a ideia.
Breve explicação: como o ~ / .bash_history não controla a contagem, primeiro determinamos o número de entradas. Então, um pouco de magia awk para obter a formatação correta e acompanhar o número de entradas.