Coloque um texto na frente de cada nova linha que um programa imprima em stdout


9

Então, eu quero fazer um log e, portanto, colocar uma data na frente da saída de um script do bash. O problema é que possui várias linhas de saída. Só consigo colocar a data antes de toda a saída. Mas então eu tenho uma linha sem uma data nos logs. É claro que posso assumir que a data da linha acima é a mesma, mas eu esperava que houvesse uma solução. Desde já, obrigado!

Este é o meu script que chama outro script:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

Esta é a saída:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

E é isso que eu gostaria de ter:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended

Acho que você não pode mudar o segundo script?
22412 jmetz #

Nah, infelizmente não. Por isso vim aqui.
23412 tzippy

Respostas:




2

Você pode usar awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awkpega um fluxo de entrada e modifica sua saída. Esse script está dizendo "imprima d seguido da saída original" e preencha dcom a data.


11
Isso não avalia a dateexpressão apenas uma vez também, para que todas essas linhas sejam impressas ao mesmo tempo?
Daniel Beck

@DanielBeck Sim, é verdade - Eu tinha assumido que estava pegando a data de cada vez, mas acabou meu teste rápido o suficiente
Paul

1

Isso imprimirá a data e a hora atuais antes de cada linha de saída de ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

Como funciona

  • set -fdesativa a expansão do bash (ou echo *não imprimiria um asterisco real).

  • while read -r LINE; do ... donesalva uma linha de saída na variável $LINEe é executada ..., até que todas as linhas sejam processadas.

  • eco $ (data "+% F% T"): "$ LINE" imprime a linha com a hora e a data atuais.

  • set +f ativa novamente a expansão do bash, para que não interfira no restante do script do bash.


Ele é avaliado apenas uma vez, para que cada um sedinsira a mesma data, imediatamente antes de iniciar o segundo script. Provavelmente não o que o usuário quer ...
Daniel Beck

Também não acho que essa tentativa funcione. AFAIK, todo o subshell é avaliado completamente primeiro e depois o loop é percorrido. Então agora os tempos são após a execução.
Daniel Beck

Seu exemplo não funciona, pois você atrasa apenas a saída, não a execução de ls. Apenas tente seu script com o seguinte script.sh: #!/bin/bash(nova linha)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Daniel Beck

Use readcom um whileloop em vez de um loop for.
26412 chepner

@chepner: Boa ideia.
Dennis
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.