Как добавить метку времени при перенаправлении стандартного вывода в файл в Bash?
У меня есть программа (сервер), и я ищу способ (сценарий), который будет перенаправлять (или лучше дублировать) весь свой стандартный stdout
в файл и добавлять метку времени для каждой записи.
Я провел некоторое исследование, и самое дальнее, что я смог получить, это благодаря тому, как добавить метку времени к перенаправлению STDERR. Он перенаправляет стандартный stdout
но добавленная временная метка соответствует времени завершения сценария:
#!/bin/bash
./server | ./predate.sh > log.txt
код predate.sh
:
#!/bin/bash
while read line ; do
echo "$(date): ${line}"
done
Кажется, что выход сервера сбрасывается после выхода из программы. (Без перенаправления он работает нормально). Кроме того, если я попытаюсь использовать predate.sh
на данном примере в упомянутой теме, он работает отлично. Я знаю, что было бы легко добавить метку времени в основную программу, но я бы предпочел не редактировать ее код.
Ответы
Ответ 1
Мне недавно нужно было точно: получать сообщения журнала в последовательной консоли (picocom), печатать их на терминале и в файл AND дописывать дату.
То, что я сейчас использую, выглядит с. например:
picocom -b 115200 /dev/tty.usbserial-1a122C | awk '{ print strftime("%s: "), $0; fflush(); }' | tee serial.txt
- вывод
picocom
подается на awk
-
awk
добавляет дату (опция %s
преобразует время в число секунд с 1970-01-01 00:00:00 UTC - или используйте %c
для удобного для чтения формата)
-
fflush()
удаляет любой буферный вывод в awk
- который отправляется на
tee
, который отсылает его в файл. (вы можете найти информацию о tee
здесь)
Ответ 2
moreutils ts
$ sudo apt-get install moreutils
$ (echo a;sleep 1;echo b;sleep 3;echo c;sleep 2;echo d;sleep 1) | ts | tee myfile
$ cat myfile
Apr 13 03:10:44 a
Apr 13 03:10:45 b
Apr 13 03:10:48 c
Apr 13 03:10:50 d
или считая от запуска программы:
$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -s
00:00:00 a
00:00:01 b
00:00:04 c
00:00:06 d
или дельты для бенчмаркинга:
$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -i
00:00:00 a
00:00:01 b
00:00:03 c
00:00:02 d
$ (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2; echo d; sleep 1) | ts -i '%.s'
0.000010 a
0.983308 b
3.001129 c
2.001120 d
См. Также: Как отслеживать, сколько раз каждая строка стандартного вывода была последней выходной строкой в Bash для сравнительного анализа?
Проверено на Ubuntu 18.04, moreutils 0.60.
Ответ 3
Для меня ваш код работает отлично [/p >
Проверьте, что я пробовал
test.sh
#!/bin/bash
while true; do
echo "hello"
done
predate.sh
#!/bin/bash
while read line; do
echo $(date) ":" $line;
done
затем
./test.sh | ./predate.sh
дает мне
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Tue Jan 14 17:49:47 IST 2014 : hello
Это можно перенаправить в какой-либо файл, используя " > " или " → " для добавления
![Check Snapshot]()
Ответ 4
Опять же, используя ts
из moreutils
, вы можете просто использовать exec вверху вашего скрипта.
#!/bin/bash
exec > >(ts>>file.log)
echo hello 1
echo hello 2
sleep 5
echo hello 3
Ответ 5
Если я понимаю, что ваша проблема заключается в том, что в файл log.txt входит файл stderr. Правильно?
Если это то, что вы хотите, это:
./server 2 > & 1 |./predate.sh > log.txt
Привет
Ответ 6
Я использую приведенный выше пример:
$ picocom -b 115200/dev/tty.usbserial-1a122C | awk '{ print strftime("%s: "), $0; fflush(); }' | tee serial.txt
выгрузить/перенаправить выходные данные telnet в файл журнала, но я не могу запустить свой сценарий в фоновом режиме. Если я использую &
для запуска в фоновом режиме, он не работает.
Точка № 1: Рабочая команда без &
:
скрипт: dumpper.sh
$ telnet $1 $2 | awk '{ print strftime("%s: "), $0;}' | tee $host.$port.log;
команда: $./dumpper.sh 16.1.1.8 202
Пункт № 2: Не работает команда с &
:
скрипт: dumpper.sh
$ telnet $1 $2 | awk '{ print strftime("%s: "), $0;}' | tee $host.$port.log 2>&1;
команда: $./dumpper.sh 16.1.1.8 20224 &
Ответ 7
Я выполняю работу cron следующим образом:
0 * * * * user /home/user/script.sh >>stdout.log
Тогда в script.sh, у меня есть что-то вроде этого:
#!/bin/bash
date
do_some_code
Поскольку "date" является частью stdout моего script.sh, метка времени является первой строкой в каждой записи stdout.log.