附加时间戳记以及日志文件行


11

我有一个日志文件,在添加时需要在每行附加时间戳。因此,我正在寻找将时间戳附加到日志行中每个条目的脚本,并且该脚本可以作为cron作业运行。

Answers:


18

一般方式

$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log

怎么运行的:

  1. cat读取称为的文件,input.log并将其打印到其标准输出流。

    通常,标准输出连接到终端,但是这个小脚本包含了一些内容,|因此shell会将的标准输出重定向cat到的标准输入sed

  2. sed读取数据(cat生成数据),处理数据(根据-e选件随附的脚本),然后将其打印到其标准输出。该脚本"s/^/$(date -R) /"意味着将行的每个开头替换为date -R命令生成的文本(replace命令的一般结构是:)s/pattern/replace/

  3. 然后根据>> bash将输出重定向sed到名为output.log>表示替换文件内容并>>表示附加到末尾)的文件。

问题是$(date -R)您在运行脚本时对它进行了一次评估,因此它将当前时间戳插入每行的开头。当前时间戳可能离生成消息的时间很远。为了避免这种情况,您必须在将消息写入文件时进行处理,而不要使用cron作业。

先进先出

上面描述的标准流重定向称为pipe。您不仅可以|在脚本中的命令之间进行重定向,还可以通过FIFO文件(也称为管道)来进行重定向。一个程序将写入文件,另一个程序将读取数据并在第一次发送时接收数据。

举个例子:

$ mkfifo foo.log.fifo
$ while true; do cat foo.log.fifo | sed -e "s/^/$(date -R) /" >> foo.log; done;

# have to open a second terminal at this point
$ echo "foo" > foo.log.fifo
$ echo "bar" > foo.log.fifo
$ echo "baz" > foo.log.fifo

$ cat foo.log      

Tue, 20 Nov 2012 15:32:56 +0400 foo
Tue, 20 Nov 2012 15:33:27 +0400 bar
Tue, 20 Nov 2012 15:33:30 +0400 baz

怎么运行的:

  1. mkfifo 创建一个命名管道

  2. while true; do sed ... ; done运行无限循环,并在每次迭代时都sed重定向foo.log.fifo到其标准输入。sed 阻止等待输入数据,然后处理收到的消息并将其打印到重定向到的标准输出中foo.log

    此时,您必须打开一个新的终端窗口,因为循环占用了当前终端。

  3. echo ... > foo.log.fifo将消息打印到重定向到fifo文件的标准输出中,并sed接收该消息,然后处理并写入常规文件。

重要的注意事项是fifo,就像任何其他管道的一侧没有连接到任何过程一样,都是没有意义的。如果您尝试写入管道,则当前进程将阻塞,直到有人读取管道另一侧的数据为止。如果要从管道读取,则该过程将阻塞,直到有人将数据写入管道为止。sed上面的示例中的循环在您执行操作之前不执行任何操作(休眠)echo

对于您的特定情况,您只需配置您的应用程序即可将日志消息写入fifo文件。如果您无法配置它-只需删除原始日志文件并创建一个fifo文件。但是,请再次注意,如果sed循环由于某种原因而终止,则尝试进入write文件的程序将被阻止,直到有人read从fifo退出为止。

好处是当程序将其写入文件时,将评估当前时间戳并将其附加到消息上。

异步处理 tailf

为了使写入日志和处理过程更加独立,可以将两个常规文件与一起使用tailf。应用程序将消息写入原始文件,其他进程读取新行(随后异步写入),并在写入第二个文件时处理数据。

让我们举个例子:

# will occupy current shell
$ tailf -n0 bar.raw.log | while read line; do echo "$(date -R) $line" >> bar.log; done;

$ echo "foo" >> bar.raw.log
$ echo "bar" >> bar.raw.log
$ echo "baz" >> bar.raw.log

$ cat bar.log

Wed, 21 Nov 2012 16:15:33 +0400 foo
Wed, 21 Nov 2012 16:15:36 +0400 bar
Wed, 21 Nov 2012 16:15:39 +0400 baz

怎么运行的:

  1. 运行tailf过程将遵循写入操作,bar.raw.log并将它们打印到重定向到无限while read ... echo循环的标准输出中。此循环执行两个操作:从标准输入读取数据到称为的缓冲区变量line,然后将生成的带有以下缓冲数据的时间戳记写入bar.log

  2. 向写入一些消息bar.raw.log。您必须在单独的终端窗口中执行此操作,因为第一个窗口将被tailf写入后的工作所占用。非常简单。

优点是,如果您杀死应用程序,则不会阻止它tailf。缺点是时间戳的准确性较低,并且日志文件重复。


谢谢你。 !因此,如何将更新日志文件中的内容重定向到此foo.log.fifo,以便它也可以附加时间。
Kratos 2012年

刚刚改善了答案。解释了为什么fifo会阻止您的tailf,并添加了正确的使用方式。实际上,with的方式tailf似乎更优雅,但是我离开了fifo方式,希望它对某人有用。
德米特里·瓦西里亚诺夫

使用您的sed答案注释vmstat输出时,时间戳不会改变。sed -e“ s / ^ / $(date -R)/”
ChuckCottrill


2

根据Dmitry Vasilyanov的答案进行了修改。

在bash脚本中,您可以动态重定向和包装带有时间戳的输出。

何时使用:

  • 对于bash脚本作业,在主脚本之前插入该行
  • 对于非脚本作业,请创建一个脚本来调用该程序。
  • 对于系统进行的服务控制,最好使用tailfDmitry Vasilyanov所说的日志文件。

名为的示例foo.sh

#!/bin/bash
exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)

echo "foo"
sleep 1
echo "bar" >&2
sleep 1
echo "foobar"

结果:

$ bash foo.sh
$ cat foo.log
May 12 20:04:11 foo
May 12 20:04:12 bar
May 12 20:04:13 foobar

怎么运行的

  1. exec &> 将stdout和stderr重定向到同一位置
  2. >( ... ) 管道输出到异步内部命令
  3. 其余部分在Dmitry Vasilyanov展开时起作用。

例如:

  • 管道时间戳记并记录到文件

    #!/bin/bash        
    exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)
    
    echo "some script commands"
    /path-to/some-thrid-party-programs
    
  • 或打印时间戳并登录到标准输出

    #!/bin/bash        
    exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line"; done;)
    
    echo "some script commands"
    /path-to/some-thrid-party-programs
    

    然后将它们保存在/etc/crontab设置中

    * * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log
    

1

我使用ts这种方法在错误日志中获得了带有时间戳的条目,该脚本用于使Cacti充满远程主机的统计信息。

为了测试仙人掌,我使用rand了一些随机值,这些值用于温度图来监视系统温度。

Pushmonstats.sh是一个脚本,用于收集我的PC的系统温度统计信息并将其发送到运行Cacti的Raspberry Pi。前段时间,网络停滞了。我的错误日志中只有SSH超时。不幸的是,该日志中没有时间条目。我不知道如何在日志条目中添加时间戳。因此,在Internet上进行了一些搜索之后,我偶然发现了这篇文章,这就是我使用的内容ts

为了测试它,我使用了一个未知选项rand。这给标准错误。为了捕获它,我将其重定向到一个临时文件。然后,我使用cat来显示文件的内容并将其通过管道传输到ts,添加我在本文中找到的时间格式,最后将其记录到错误文件中。然后,我清除临时文件的内容,否则对于相同的错误,我将得到两次输入。

Crontab:

* * * * * /home/monusr/bin/pushmonstats.sh 1>> /home/monusr/pushmonstats.log 2> /home/monusr/.err;/bin/cat /home/monusr/.err|/usr/bin/ts %F-%H:%M:%.S 1>> /home/monusr/pushmonstats.err;> /home/monusr/.err

这在我的错误日志中提供了以下内容:

2014-03-22-19:17:53.823720 rand: unknown option -- '-l'

也许这不是一个非常优雅的方法,但是它可以工作。我想知道是否有更优雅的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.