Desejo acrescentar um carimbo de data e hora a cada linha de saída de um comando. Por exemplo:
foo
bar
baz
se tornaria
[2011-12-13 12:20:38] foo
[2011-12-13 12:21:32] bar
[2011-12-13 12:22:20] baz
... onde a hora sendo prefixada é a hora em que a linha foi impressa. Como posso conseguir isso?
Respostas:
O moreutils inclui o
ts
que faz isso muito bem:command | ts '[%Y-%m-%d %H:%M:%S]'
Também elimina a necessidade de um loop, cada linha de saída terá um carimbo de data / hora.
Você quer saber quando o servidor voltou, você reiniciou? Apenas corra
ping | ts
, problema resolvido: D.fonte
tail -f /tmp/script.results.txt | ts
ssh -v 127.0.0.1 2>&1 | ts
-s
é útil. Como isso exibe o tempo de execução do comando. Pessoalmente, gosto de usar os doists
ets -s
ao mesmo tempo. É algo como isto:command | ts -s '(%H:%M:%.S)]' | ts '[%Y-%m-%d %H:%M:%S'
. Isso precede as linhas de log da seguinte maneira:[2018-12-04 08:31:00 (00:26:28.267126)] Hai <3
Em primeiro lugar, se você espera que esses registros de data e hora realmente representem um evento, lembre-se de que, como muitos programas executam buffer de linha (alguns de forma mais agressiva que outros), é importante pensar nisso o mais próximo possível do tempo que a linha original teria. foi impresso em vez de um carimbo de data e hora de uma ação em andamento.
Você também pode verificar se o seu comando ainda não possui um recurso embutido dedicado a isso. Como exemplo,
ping -D
existe em algumasping
versões e imprime o tempo desde a época do Unix antes de cada linha. Se seu comando não contiver seu próprio método, no entanto, existem alguns métodos e ferramentas que podem ser empregados, entre outros:Shell POSIX
Lembre-se de que, como muitos shells armazenam suas seqüências internamente como cstrings, se a entrada contiver o caractere nulo (
\0
), isso poderá fazer com que a linha termine prematuramente.GNU awk
Perl
Pitão
Rubi
fonte
stdbuf -o 0
, mas se o programa estiver manipulando manualmente seu buffer de saída, isso não ajudará (a menos que haja uma opção para desativar / reduzir o tamanho do buffer de saída).python -u
... for x in sys.stdin
itera sobre linhas sem armazená -las todas na memória primeiro.Para uma medição delta linha a linha, tente o gnomon .
fonte
ts
usar processos ao vivo. Emborats
seja mais adequado para processos não interativos.O post de Ryan fornece uma ideia interessante, no entanto, falha em vários aspectos. Ao testar com
tail -f /var/log/syslog | xargs -L 1 echo $(date +'[%Y-%m-%d %H:%M:%S]') $1
, notei que o carimbo de data / hora permanece o mesmo, mesmo questdout
venha mais tarde com diferença de segundos. Considere esta saída:Minha solução proposta é semelhante, mas fornece registro de data e hora adequado e usa um pouco mais portátil em
printf
vez deecho
Por que
bash -c '...' bash
? Porque devido à-c
opção, o primeiro argumento é atribuído$0
e não aparece na saída. Consulte a página de manual do seu shell para obter a descrição adequada de-c
Testar esta solução com
tail -f /var/log/syslog
e (como você provavelmente poderia adivinhar) desconectar e reconectar-se ao meu wifi mostrou o registro de data e hora adequado fornecido por ambosdate
e porsyslog
mensagensO Bash pode ser substituído por qualquer casco tipo bourne, pode ser feito com um
ksh
oudash
, pelo menos, aqueles que têm-c
opção.Questões potenciais:
A solução exige ter
xargs
, disponível em sistemas compatíveis com POSIX, portanto, a maioria dos sistemas semelhantes ao Unix deve ser coberta. Obviamente, não funcionará se o seu sistema não for compatível com POSIX ou não tiverGNU findutils
fonte
Eu preferiria comentar acima, mas não posso, reputacionalmente. De qualquer forma, a amostra Perl acima pode ser inalterada da seguinte maneira:
O primeiro '$ |' abafadores STDOUT. O segundo define o stderr como o canal de saída padrão atual e o armazena em buffer. Como select retorna a configuração original de $ |, envolvendo o select dentro de um select, também redefinimos $ | para o padrão, STDOUT.
E sim, você pode cortar e colar como está. Eu multi-alinhado para legibilidade.
E se você realmente quer ser preciso (e você tem o Time :: Hires instalado):
fonte
A maioria das respostas sugere usar
date
, mas é lenta o suficiente. Se sua versão do bash for maior que a 4.2.0, é melhor usá-printf
lo, é um bash embutido. Se você precisar oferecer suporte a versões legadas do bash, poderá criar alog
função depende da versão do bash:Veja as diferenças de velocidade:
UPD: em vez de
$(date +"${TIMESTAMP_FORMAT}")
ser melhor usar$(exec date +"${TIMESTAMP_FORMAT}")
ou até$(exec -c date +"${TIMESTAMP_FORMAT}")
acelerar a execução.fonte
Você pode fazer isso com
date
exargs
:Explicação:
xargs -L 1
diz ao xargs para executar o comando de prosseguimento para cada 1 linha de entrada e passa na primeira linha ao fazê-lo.echo `date +'[%Y-%m-%d %H:%M:%S]'` $1
basicamente ecoa a data com o argumento de entrada no finalfonte
$1
. Isso não é bom estilo. Sempre cite as variáveis. Além disso, você está usandoecho
, o que não é portátil. Está tudo bem, mas pode não funcionar corretamente em alguns sistemas.date
seja reavaliado a cada linha, ou é praticamente impossível?