簡體   English   中英

通過命名管道或 rsyslog 添加時間戳到 systemd 管理服務的日志 output

[英]Adding timestamps via named pipes or rsyslog to the log output of a systemd-managed service

我不得不處理一項專有的遺留服務(在 Debian 10 上運行),該服務將各種(大致)信息和通知級別的內容記錄到標准輸出中,並將(大致)警告和錯誤級別的內容記錄到標准錯誤中。 兩者都可以使用--stdout <path>--stderr <path>命令行參數寫入文件。 這個守護進程的 systemd 單元文件看起來像這樣(刪減到最基本的部分):

[Unit]
Description=Some legacy proprietary thing
After=network.target

[Service]
ExecStart=/usr/local/bin/thing \
  --stdout /var/log/thing/stdout.log \
  --stderr /var/log/thing/stderr.log

[Install]
WantedBy=multi-user.target

問題是寫入 stdout.log 和 stderr.log 的行不包含我們現在需要的時間戳。 該應用程序對我們來說是一個黑盒子,修改其日志記錄 output 以包含時間戳是不可行的。

在我的研究中,我遇到了兩個可能適用於此的選項。 如果你有其他人,我很想聽聽他們的意見。

選項1

使用mkfifo為 stdout 和 stderr 創建命名管道,並使遺留應用程序將它們用作--stdout--stderr目標。 然后,設置一個進程來讀取這些管道,將每一行管道傳輸到ts命令,這會添加一個很好的時間戳,如下所示:

$ echo foo | ts '[%Y-%m-%d %H.%M.%.S]'
[2021-08-10 16.16.21.506571] foo

這些帶時間戳的行隨后將被寫入日志文件,一個用於 stdout,一個用於 stderr,可能通過管道。

選項 2

在 systemd 單元文件中,我們可以將StandardOutputStandardError設置為syslog ,然后將 SyslogIdentifier 設置為我們可以與SyslogIdentifier一起使用的某個字符串,添加時間戳並將最后一行寫入日志文件。

不幸的是,我還沒有找到讓 systemd 區分 stdout 和 stderr 的方法:它們都將被發送到 rsyslog 而沒有任何關於哪個是來源的信息。 (我知道SyslogLevelPrefix ,但這需要來自我們黑盒應用程序的傳入日志消息包含sd-daemon(3)樣式前綴,而這目前是不可行的。)

細節

由於選項 2 固有的問題,我將進一步討論選項 1。 如果您知道 syslog 方法的解決方法,請分享 n.netheless。

所以,命名管道很棒,但我不知道如何在 systemd 單元文件中實現它們。 我想我必須有兩個單獨的讀取器進程,一個用於 stdout pipe,一個用於 stderr pipe,因此需要兩個新的單元文件。 一些進一步的注意事項:

  • 命名管道應該在編寫器應用程序啟動之前存在。 我可以事先用mkfifo創建它們,所以這應該不是問題。 沒有必要使用 systemd 管理管道的存在,除非它以某種方式使單元文件更簡單或更健壯。
  • 執行時間戳增加和日志文件寫入的讀取器進程應該在寫入器應用程序啟動之前啟動並運行,我相信這是單元文件中的Before/AfterRequires/Wants的工作。
  • 整個裝置應該在寫入器應用程序或讀取器進程重啟后仍然存在。 例如,如果在讀取進程中使用cat ,寫入進程退出並且cat看到 EOF 並退出,則讀取進程應該恢復並在寫入進程恢復時做好准備。
  • 當相應的讀取器進程關閉時,應用程序寫入命名管道的任何日志行都將丟失,但這是可以接受的。

由於編寫器進程具有參數--stdout /path/to/outfifo --stderr /path/to/errfifo ,從理論上講,讀取器進程可以像這樣簡單:

cat /path/to/outfifo | ts '[%Y-%m-%d %H.%M.%.S]' > /var/log/thing/stdout_ts.log
cat /path/to/errfifo | ts '[%Y-%m-%d %H.%M.%.S]' > /var/log/thing/stderr_ts.log

添加一個帶有copytruncatelogrotate規則,我們很成功,除了我不知道如何在 systemd 單元文件中執行此操作。 同時滿足上述可重啟性要求。

如果您能幫助構建單元文件,或提出替代方法,我將不勝感激。

journald可以為您添加時間戳等。

一個簡單的解決方案是使用systemd-cat

ExecStart=/bin/systemd-cat \
  --priority=info \
  --stderr-priority=warning \
  --identifier=thing \
  /usr/local/bin/thing

如果您thing為優先級發出記錄器前綴(例如,以<4>開頭的行表示warning消息),那么您可以使用--level-prefix標志而不是手動設置優先級。

其他一些想法包括:

  • 使用stream 登錄您的設備。
  • 編寫自定義拆分器以讀取日志並將它們 pipe 到具有正確級別的systemd-cat 你可以把它作為一個服務來運行,這個thing會與之交談。
  • 變體:編寫自定義解析器並通過sd_journal_send(3)將解析后的日志直接發送到 journald。 您將使用 systemd 將 pipe output 的thing交給parser
  • 使用 systemd 通過StandardOutput=StandardError=將 stdout 和 stderr 寫入套接字單元

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM