Linux 的log 機制

會有這篇文章,主要還是因為在工作上踩了好幾次坑,很多次都遇到了log檔佔用了太多的硬碟空間,所以趁這機會好好研究一下linux上相關的設定。

在Linux上Distro,Log 相關的 daemon主要有以下幾個:
(1) rsyslogd
(2) systemd-journald
(3) logrotate.d
而它們各自有不同的工作要處理,下面就分別來介紹每個daemon service:

rsyslogd

 rsyslogd is the enhancement of syslogd, a service that takes care of managing centralized log files. Syslogd has been around for a long time.

https://www.golinuxcloud.com/systemd-journald-how-logging-works-rhel-7/

rsyslogd 算是syslogd的進化版本,相對於syslogd, 它提供更有效率的log 處理方式

預設的log 會寫入到/var/log/syslog 裡,而相關的設定檔則是放在/etc/rsyslog.conf/etc/rsyslog.d/50-default.conf裡面。

在ubuntu20.04中,rsyslog.conf 的設定來看,它預設是從imuxsock裡讀取到log 訊息,並寫入到/var/log/syslog之中。相關在rsyslog.conf的設定如下:

module(load="imuxsock") # provides support for local system logging

另外,在ubuntu中,是使用systemctl來執行這個daemon,所以我們可以透過下面這個指令來看其執行狀態:

sudo systemctl status rsyslog.service

而相關的輸出大概會是長這樣:

● rsyslog.service - System Logging Service
      Loaded: loaded (/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
      Active: active (running) since Thu 2021-08-26 11:12:02 UTC; 1 weeks 1 days ago
 TriggeredBy: ● syslog.socket
        Docs: man:rsyslogd(8)
              https://www.rsyslog.com/doc/
    Main PID: 269574 (rsyslogd)
       Tasks: 4 (limit: 9369)
      Memory: 517.1M
      CGroup: /system.slice/rsyslog.service
              └─269574 /usr/sbin/rsyslogd -n -iNONE

簡單講,rsyslogd 主要就是負責系統所有相關的log的寫入,像是/var/log/syslog, /var/log/auth.log, /var/log/kern.log
不過對於log 寫入之外的工作,就不是由它來負責的了,而是由另一個服務logrotate來負責的。

更改設定檔以後,則要使用sudo systemctl restart rsyslog.service來重啟服務以讀取新的設定檔

logrotate

從名稱上就可以看得出,這個service主要負責的工作就是做log file的rotate,所以當我們發現/var/log/syslog的檔案過大時,很大一部分的原因會是我們沒有設定好 /var/log/syslog的rotate設定。

logrotate 的設定檔位置在/etc/logrotate.conf,裡面有定義了預設的log檔案rotate設定;而針對於不同log的rotate 客制化設定,則是放在/etc/logrotate.d/ 這個資料夾下面。

舉例來說,是rsyslog的log rotate 設定的位置就是在/etc/logrotate.d/rsyslog 這裡。而相關的範例設定如下:

/var/log/syslog
 {
     rotate 7
     hourly
     maxsize 100M
     missingok
     notifempty
     delaycompress
     compress
     postrotate
         /usr/lib/rsyslog/rsyslog-rotate
     endscript
 }
 /var/log/mail.info
 /var/log/mail.warn
 /var/log/mail.err
 /var/log/mail.log
 /var/log/daemon.log
 /var/log/kern.log
 /var/log/auth.log
 /var/log/user.log
 /var/log/lpr.log
 /var/log/cron.log
 /var/log/debug
 /var/log/messages
 {
     rotate 4
     weekly
     missingok
     notifempty
     compress
     delaycompress
     sharedscripts
     postrotate
         /usr/lib/rsyslog/rsyslog-rotate
     endscript
 }

NOTE:
如果rotate的timesize都有設定的話,那就會以size為基準。而目前設定檔time最多只能支援到hourly
不過如果是以size為基準的話,應該也可以設定每分鐘的cron job,定期執行logrotate

另外,與一般的system service不一樣的地方是,logrotate是透過cron job的方式執行的,它的基本運作方式是,當我們執行了下面的指令去讀取新的rotate設定時

sudo logrotate /etc/logrotate.conf

logrotate 這個程式除了會去執行對應的rotate工作外,還會根據設定去產生對應的cron jobs。
舉例來說,如果我們設定syslog的rotate檢查頻率為hourly,那我們就可以找到對應的/etc/cron.hourly/logrotate 的cron job。

更改設定檔以後,則要使用sudo logrotate /etc/logrotate.conf來重啟服務以讀取新的設定檔

systemd-journald

 With the introduction of systemd, the journald log service systemd-journald has been introduced also. This service is tightly integrated with systemd, which allows administrators to read detailed information from the journal while monitoring service status using the systemctl status command.

https://www.golinuxcloud.com/systemd-journald-how-logging-works-rhel-7/

journald 是近年來在Linux上常被預設啟用的另一個log deamon service,它主要與systemd services 作整合,而與rsyslogd不同之處可以參考這裡:

Journald provides structure and indexed log files (called journals) in a secure manner. Therefore, not only are the journal files easier to search, it is harder for system intruders to cover their tracks.. Also you can maintain rsyslog messages in structured format.

Another advantage of using the systemd-journald service over traditional logging daemons is that journal files are automatically rotated if they grow above certain limits. This reduces log file maintenance issues and complexity.

The journalctl utility is used to read the journal binary log files and this command provides several means of filtering the data which is very powerful.

https://www.golinuxcloud.com/systemd-journald-how-logging-works-rhel-7/

簡單來說,它可以看成是rsyslogd的加強版,除了提供更安全的log儲存方式外,還額外提供了log rotate的功能,另外其搭配的cli journalctl還可以方便使用者檢索需要的log內容。

基本上journald的儲存相關設定主要是分為runtimesystem:

  • runtime: 所以runtime 相關的journals 會存放在/run/log/journal/下,一旦重新開機以後,舊的journals是不會保留的。
  • system: 如果下面的路徑/var/log/journal 存在且有對應的權限時,那麼journald就不會去寫log到/run/log/journal/底下了,而是持續性的寫入到/var/log/journal/下,在這情況下,即使重開機以後,舊的journals還是會保留的。

在ubuntu20.04中,journald的log 存放位置是在/var/log/journal,而設定檔的位置則是在/etc/systemd/journald.conf。 相關的設定檔說明可以參考ubuntu這文章

journald預設是透過systemd service的方式啟用的,所以透過下面的指令可以看得出目前journald的運作狀況:

sudo systemctl status systemd-journald.service

範例輸出結果為:

● systemd-journald.service - Journal Service
      Loaded: loaded (/lib/systemd/system/systemd-journald.service; static; vendor preset: enabled)
      Active: active (running) since Wed 2021-07-28 09:56:47 UTC; 1 months 7 days ago
 TriggeredBy: ● systemd-journald-dev-log.socket
              ● systemd-journald-audit.socket
              ● systemd-journald.socket
        Docs: man:systemd-journald.service(8)
              man:journald.conf(5)
    Main PID: 186 (systemd-journal)
      Status: "Processing requests…"
       Tasks: 1 (limit: 9369)
      Memory: 39.4M
      CGroup: /system.slice/systemd-journald.service
              └─186 /lib/systemd/systemd-journald
 Warning: journal has been rotated since unit was started, output may be incomplete.

journalctl 指令的使用

通常主要是透過journalctl指令來讀取log與變更log檔的一些設定,一些透過journalctl過濾/讀取log的相關技巧可以參考這邊

而一些常用journal 相關的管理指令如下:

  • 顯示目前所有journal的在硬碟上的使用空間
journalctl --disk-usage

  • 一次性的限制所有journal可以使用的硬碟空間 (e.g. 1GB),另外在清理時只會針對被archived 過的journal作清理。
sudo journalctl --vacuum-size=1G

更多journald 與rsyslog的整合與比較可以參考這裡

相關設定以確保log 檔案不會過大

在了解rsyslog, logroatejournald的一些運作模式以後,接下來回到之前常遇到的問題,log檔案size過大,而導致系統運作不正常的這個問題。

由於ubuntu20.04預設是同時會執行rsyslogdjournald的,所以基本上我們要關注的log檔案有兩個位置,分別是/var/log/syslog/var/log/journal

syslog的相關設定

基本上,針對sysloglogrotate預設是每天會做一次rotate,所以為了避免我們的應用程式在短時間製造過多的log,我們可以修改/etc/logrotate.d/rsyslog如下:

sudo vim /etc/logrotate.d/rsyslog

接著修改設定檔中的/var/log/syslog 部分如下

/var/log/syslog
 {
     rotate 3
     hourly
     maxsize 100M
     missingok
     notifempty
     delaycompress
     compress
     postrotate
         /usr/lib/rsyslog/rsyslog-rotate
     endscript
 }

以這樣來限制syslog的檔案大小

journald

以ubuntu20.04為例,它預設就是寫入到/var/log/journal,也就是說,我們必須去設定/etc/systemd/journald.conf 中的System*相關參數,詳細設定如下:

SystemMaxUse=1G
SystemKeepFree=
SystemMaxFileSize=100M
SystemMaxFiles=10

清除過大的log檔案

SYSLOG

如果目前的syslog 真的長的太大了,且裡面的內容是可丟棄的情況下,則可以使用下面的指令來清空目前的/var/log/syslog

#  this command needs to be ran as root
> /var/log/syslog

JOURNAL

如果是journal的話,則可以先將目前的journal archived,再做清理,詳細指令如下:

sudo journalctl --rotate
sudo journalctl --vacuum-time=1s

其它相關的清理方式可以參考這裡

reference: