Назад | Перейти на главную страницу

Как добавить метку времени в журнал сценария bash?

У меня есть постоянно работающий скрипт, который я вывожу в файл журнала:

script.sh >> /var/log/logfile

Я хотел бы добавить метку времени перед каждой строкой, добавляемой в журнал. Подобно:

Sat Sep 10 21:33:06 UTC 2011 The server has booted up.  Hmmph.

Можно ли использовать джиу-джитсу?

Вы можете передать вывод скрипта через цикл с префиксом текущей даты и времени:

./script.sh | while IFS= read -r line; do printf '%s %s\n' "$(date)" "$line"; done >>/var/log/logfile

Если вы будете использовать это часто, легко создать функцию bash для обработки цикла:

adddate() {
    while IFS= read -r line; do
        printf '%s %s\n' "$(date)" "$line";
    done
}

./thisscript.sh | adddate >>/var/log/logfile
./thatscript.sh | adddate >>/var/log/logfile
./theotherscript.sh | adddate >>/var/log/logfile

Видеть ts из Ubuntu moreutils пакет:

command | ts

Или если $command выполняет автоматическую буферизацию (требуется expect-dev пакет):

unbuffer command | ts

В Дата команда предоставит эту информацию

date -u
Sat Sep 10 22:39:24 UTC 2011

так что вы можете

echo $(date -u) "Some message or other"

это то, что ты хотел?

Вы можете просто эхо команда выводит в файл журнала. т.е.

echo "`date -u` `./script.sh`" >> /var/log/logfile

Это действительно работает :)

Пример:

[sparx@E1]$ ./script.sh 
Hello Worldy
[sparx@E1]$ echo "`date -u` `./script.sh`" >> logfile.txt
[sparx@E1]$ cat logfile.txt 
Mon Sep 12 20:18:28 UTC 2011 Hello Worldy
[sparx@E1]$ 

Делать config.sh файл

#!/usr/bin/env bash
LOGFILE="/path/to/log.log"
TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`

Когда вам нужно отправить в файл журнала, используйте

#!/usr/bin/env bash
source /path/to/config.sh

echo "$TIMESTAMP Say what you are doing" >> $LOGFILE

do_what_you_want >> $LOGFILE

Файл журнала будет выглядеть так

2013-02-03 18:22:30 Say what you are doing

Так будет легко сортировать по дате

Принятый ответ https://serverfault.com/a/310104 может быть немного медленным, если нужно обработать много строк, с накладными расходами на запуск date процесс, позволяющий около 50 строк в секунду в Ubuntu и только около 10-20 в Cygwin.

когда bash можно предположить, что более быстрой альтернативой будет printf встроенный с его %(...)T спецификатор формата. Сравнить

>> while true; do date; done | uniq -c
     47 Wed Nov  9 23:17:18 STD 2016
     56 Wed Nov  9 23:17:19 STD 2016
     55 Wed Nov  9 23:17:20 STD 2016
     51 Wed Nov  9 23:17:21 STD 2016
     50 Wed Nov  9 23:17:22 STD 2016

>> while true; do printf '%(%F %T)T\n'; done | uniq -c
  20300 2016-11-09 23:17:56
  31767 2016-11-09 23:17:57
  32109 2016-11-09 23:17:58
  31036 2016-11-09 23:17:59
  30714 2016-11-09 23:18:00

Вы имеете в виду как:

(date && script.sh) >> /var/log/logfile

Попробуй это

timestamp()
{
 date +"%Y-%m-%d %T"
}

Вызовите эту функцию отметки времени в каждой команде echo:

echo "$(timestamp): write your log here" >> /var/log/<logfile>.log

Краткий ответ, отформатированный в соответствии с вопросом

script.sh | gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' >> /var/log/logfile

Объяснение

awk быстро бегает и может работать как конвейерный фильтр Unix и напечатать дату отдельно.

gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }'

Давайте протестируем это:

yes |head -5000000 |gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }' |uniq -c
 461592 [2017-02-28 19:46:44] y
 488555 [2017-02-28 19:46:45] y
 491205 [2017-02-28 19:46:46] y
 498568 [2017-02-28 19:46:47] y
 502605 [2017-02-28 19:46:48] y
 494048 [2017-02-28 19:46:49] y
 493299 [2017-02-28 19:46:50] y
 498005 [2017-02-28 19:46:51] y
 502916 [2017-02-28 19:46:52] y
 495550 [2017-02-28 19:46:53] y
  73657 [2017-02-28 19:46:54] y

Дополнительная информация

Сед бежит намного быстрее,

sed -e "s/^/$(date -R) /"

yes |head -5000000 |sed -e "s/^/$(date -R) /" |uniq -c
5000000 Tue, 28 Feb 2017 19:57:00 -0500 y

Однако при ближайшем рассмотрении кажется, что время не меняется.

vmstat 1 | sed -e "s/^/$(date -R) /"

Так как date (который, кстати, медленнее) вызывается только один раз.

Ниже приведено содержимое моего файла журнала.

xiongyu@ubuntu:~/search_start_sh$ tail restart_scrape.log 

2017-08-25 21:10:09 scrape_yy_news_main.py got down, now I will restart it

2017-08-25 21:10:09 check_yy_news_warn.py got down, now I will restart it

2017-08-25 21:14:53 scrape_yy_news_main.py got down, now I will restart it

часть моего содержимого оболочки, как показано ниже

log_file="restart_scrape.log"
TIMESTAMP=`date "+%Y-%m-%d %H:%M:%S"`
echo "$TIMESTAMP $search_py_file got down, now I will restart it" | tee -a $log_file 

Этот сценарий распечатывает вывод в терминале, а также сохраняет в файле журнала.

#!/bin/bash

MY_LOG=/var/log/output.log

echolog(){
    if [ $# -eq 0 ]
    then cat - | while read -r message
        do
                echo "$(date +"[%F %T %Z] -") $message" | tee -a $MY_LOG
            done
    else
        echo -n "$(date +'[%F %T %Z]') - " | tee -a $MY_LOG
        echo $* | tee -a $MY_LOG
    fi
}

echolog "My script is starting"
whoami | echolog

Пример вывода:

[2017-10-29 19:46:36 UTC] - My script is starting
[2017-10-29 19:46:36 UTC] - root

Другой вариант - настроить функцию для вызова каждый раз, когда вы хотите вывести данные в свой код:

PrintLog(){
  information=$1
  logFile=$2
  echo "$(date +'%Y-%m-%d %H:%M:%S" $information} >> $logFile
}

Затем каждый раз в вашем коде вы хотите отправить его в файл журнала.

PrintLog "Stuff you want to add..." ${LogFileVariable}

Очень просто....

Введите "sed":

script.sh | sed "s|^|$('date') :: |" >> /var/log/logfile

Я просто так делаю (buddy переменная - это просто пример, вы можете поместить туда что угодно):

#!/bin/bash
now=$( date +%Y%m%d-%H%M-%S )
buddy=`cat /proc/buddyinfo | grep Normal`
echo "$now, $buddy" >> /home/myuser/buddyinfo-logger.log

Это прекрасно работает.