将时间戳记与日志文件行一起附加

Kra*_*tos 12 logs date

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

Dmi*_*try 19

一般方式

$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

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

    通常标准输出连接到终端,但是这个小脚本包含|所以 shell 将标准输出重定向catsed.

  2. sed读取数据(cat产生它),处理它(根据-e选项提供的脚本),然后将其打印到其标准输出。该脚本"s/^/$(date -R) /"意味着将行的每个开头替换为由date -R命令生成的文本(替换命令的一般结构是:)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
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

  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
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

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

  2. 写一些消息到bar.raw.log. 您必须在单独的终端窗口中执行此操作,因为第一个将被占用tailf,它将跟随写入并完成其工作。非常简单。

优点是如果你杀死了你的应用程序不会阻塞tailf。缺点是不太准确的时间戳和重复的日志文件。


Sté*_*las 6

您可以使用以下tsperl 脚本moreutils

$ echo test | ts %F-%H:%M:%.S
2012-11-20-13:34:10.731562 test
Run Code Online (Sandbox Code Playgroud)