Logs

附加時間戳以及日誌文件行

  • May 2, 2020

我有一個日誌文件,我需要在每行添加時間戳時附加它們。因此,我正在尋找將時間戳附加到日誌行中的每個條目並且可以作為 cron 作業執行的腳本。

一般方式

$ 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(替換命令的一般結構是:)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接收它並處理並寫入正常文件。

重要的注意事項是先進先出,就像任何其他管道如果其一側未連接到任何程序就沒有意義一樣。如果您嘗試寫入管道,目前程序將阻塞,直到有人讀取管道另一端的數據。如果您想從管道中讀取,該程序將阻塞,直到有人將數據寫入管道。上例中的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,它將跟隨寫入並完成其工作。非常簡單。

優點是如果你 kill ,你的應用程序不會阻塞tailf。缺點是不太準確的時間戳和重複的日誌文件。

引用自:https://unix.stackexchange.com/questions/56189