Поместите текст перед каждой новой строкой, которую программа выводит на стандартный вывод

9

Поэтому я хочу заняться журналированием и для этого поставить дату перед выводом bash-скрипта. Проблема в том, что он имеет несколько строк вывода. Я могу только поставить дату перед всем выводом. Но тогда у меня есть строка без даты в журналах. Конечно, я могу предположить, что дата из строки выше совпадает, но я надеялся, что есть решение. Заранее спасибо!

Это мой скрипт, который вызывает другой скрипт:

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

Это вывод:

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

И это то, что я хотел бы иметь:

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
tzippy
источник
Я не думаю, что вы могли бы просто изменить второй сценарий?
Jmetz
Нет, к сожалению нет. Вот почему я пришел сюда.
Циппи
2
Связанный: stackoverflow.com/questions/21564/… Также: stackoverflow.com/a/1508098/259953
Der Hochstapler

Ответы:

9

По аналогичному вопросу о переполнении стека , есть 2 отличных варианта.

awk ( ответ )

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

аннотировать ( ответить )

annotate - это небольшой bash-скрипт, который можно получить напрямую по приведенной здесь ссылке или в системах на основе Debian через пакет devscripts(в форме annotate-output).

Оливер Зальцбург
источник
3

Я думаю, что вы можете использовать awk для этого:

./script.sh | awk '{ print strftime()" : "$0; }'

(см. http://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html для форматирования даты, возвращаемой strftime ())

Flinth
источник
2
awk: calling undefined function strftime- это специфично для gawk?
Даниэль Бек
Теперь, когда вы упомянули об этом, да, похоже, это: /
Flinth
2

Ты можешь использовать awk

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

awkберет входной поток и модифицирует его вывод. Этот скрипт говорит: «печать d с последующим исходным выводом», а затем заполняется dдатой.

Павел
источник
1
Разве это не оценивает dateвыражение только один раз, так что все такие строки печатаются одновременно?
Даниэль Бек
@DanielBeck Да, так и есть - я предполагал, что каждый раз выбирает дату, но достаточно быстро закончил тест
Пол
1

Это напечатает текущую дату и время перед каждой строкой вывода ./script.sh:

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

Как это работает

  • set -fотключает расширение bash (или echo *не печатает настоящую звездочку).

  • while read -r LINE; do ... doneсохраняет одну строку вывода в переменной $LINEи выполняется ...до тех пор, пока не будут обработаны все строки.

  • echo $ (date "+% F% T"): "$ LINE" печатает строку с текущим временем и датой.

  • set +f снова включает расширение bash, чтобы оно не мешало остальной части сценария bash.

Деннис
источник
Он оценивается только один раз, поэтому каждый sedвставляет одну и ту же дату, непосредственно перед запуском второго скрипта. Вероятно, не то, что хочет пользователь ...
Даниэль Бек
Я не думаю, что эта попытка тоже сработает. AFAIK, сначала полностью оценивается подоболочка, а затем обходится цикл. Так что теперь время после казни.
Даниэль Бек
Ваш пример не работает, так как вы только задерживаете вывод, а не выполнение ls. Просто попробуйте свой сценарий со следующим script.sh: #!/bin/bash(новая строка)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Даниэль Бек
Используйте readс whileциклом вместо цикла for.
Чепнер
@chepner: хорошая идея.
Деннис