Como ter o histórico de comandos com a impressão de data e hora no terminal continuamente?

8

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?

    
por jus cogens prime 28.05.2014 / 02:37

3 respostas

6

Com o GNU awk :

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

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})'$PS1

Onde${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)'$PS1

Nã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 para definir uma variável de rastreamento persistente no shell atual, apesar de ter que rastreá-lo e processá-lo em subshells dentro da sequência de prompt.

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}
    
por 29.05.2014 / 08:33
4

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.

    
por 28.05.2014 / 03:50