题 如何为bash脚本日志添加时间戳?


我有一个不断运行的脚本,我输出到日志文件:

script.sh >> /var/log/logfile

我想在追加到日志的每一行之前添加一个时间戳。喜欢:

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

我可以使用任何柔术吗?


77
2017-09-10 21:35




看到这个任务。 serverfault.com/questions/80749/...。这里有几个答案。 - Zoredache
对于awk / gawk解决方案,请参阅: stackoverflow.com/questions/21564/... - User


答案:


您可以通过前缀当前日期和时间的循环来管道脚本的输出:

./script.sh | while IFS= read -r line; do echo "$(date) $line"; done >>/var/log/logfile

如果您将使用它很多,那么很容易使用bash函数来处理循环:

adddate() {
    while IFS= read -r line; do
        echo "$(date) $line"
    done
}

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

78
2017-09-10 21:58



@Nils这是一个预防的伎俩 read 从修剪开头和行的空白。它将IFS(bash的内部字段分隔符,基本上是空格字符列表)设置为空 read 命令。 - Gordon Davisson
...和-r忽略转义字符“\”。这应该适用于所有情况 - 脚本编写很棒。 - Nils
@Nils它不是完全防弹,因为一些实现 echo 解释转义序列。如果你 真 希望它不要弄乱内容(除了添加日期),替换 echo 命令用 printf "%s %s\n" "$(date)" "$line" - Gordon Davisson
你可能对a感兴趣 符合ISO-8601标准 日期/时间戳: date -u +"%Y-%m-%dT%H:%M:%SZ" 或者更漂亮 date +"%Y-%m-%d %T"。 - Pablo Bianchi
当这个脚本按预期工作时,它会生成一个新进程(执行 date)为 每 日志行,这可能是一个巨大的缺点,具体取决于您的机器和日志量。我宁愿建议使用 ts 如果可以的话,请参阅@willem的答案 - Michael Schaefers


请参阅Ubuntu“moreutils”pkg中的“ts”:

command | ts

或者,如果$ command执行自动缓冲(需要expect-dev pkg):

unbuffer command | ts

41
2017-10-29 15:20





你可以简单 回声 该命令输出到日志文件。即

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]$ 

11
2017-09-10 22:03



嗯不适合我。 - Antonius Bloch
你执行命令时得到了什么? - SparX
这将时间戳放在''./script.sh''的整个输出之前,而不是在每一行之前。 - clacke


日期 命令将提供该信息

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

所以你可以

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

那是你想要的吗?


10
2018-02-03 17:23



使用date命令是我的想法,但是我无法将其添加到脚本本身,所以我正在寻找的是改变这一行的方法:“script.sh”/ var / log / logfile“追加日期。 - Antonius Bloch
在这种情况下,将脚本的输出重定向到命名管道并让守护程序监听输出,该守护程序接受脚本输出并在将其写入日志文件之前添加日期。你可以修改一下 我写的脚本 在这做这个。我会这样做,因为它让我感兴趣但是在英国已经很晚了,我明天就会提前开始。 - Iain


做一个 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

因此按日期排序很容易


7
2017-09-12 20:34



你的''config.sh''将在''source ... / config.sh''上运行''date''一次。 - clacke


你的意思是:

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

5
2018-04-27 16:45



我的上帝,人们,每个人都在做后退替换,命名管道等。只需将日期命令和脚本都包含在parens中!拥有该函数的人有一个合法的情况,如果有多行输出,并且日志需要看起来漂亮的每一行上的日期,但大多数这些解决方案是过度的,不使用shell语义。 - cjc
这只会在每次执行时添加一次时间戳 script.sh。 OP需要每行的时间戳。 - Dave Forgac
虽然这不能回答OP问题但我仍然发现它有用的信息。 - User


试试这个

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

在每个echo命令中调用此时间戳函数:

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

3
2017-11-09 22:24



@ shazbot:感谢您的编辑,这是一个错字错误,我没注意到。 - Sanjay Yadav


接受的答案 https://serverfault.com/a/310104 可能有点慢,如果必须处理很多行,开始的开销 date 在Ubuntu中允许每秒大约50行,在Cygwin中只允许大约10到20行。

什么时候 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

3
2017-08-26 01:51





以下是我的日志文件内容

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

我的一些shell内容如下

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 

1
2018-03-30 13:48





另一种选择是设置一个函数,以便在每次要在代码中输出数据时调用:

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

然后每次在您的代码中,您希望将其发送到日志文件调用

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

十分简单....


1
2018-03-25 11:15