如何在 Ubuntu 18.04/20.04 上使用 Logrotate 設置日誌輪換

日誌文件旨在將有關係統活動的信息保留一段合理的時間,但係統日誌守護程序不提供控制日誌文件大小的方法。 因此,如果不加以檢查,日誌文件可能會增長到消耗它們所在的所有可用分區空間。 為了防止日誌文件完全填滿您的系統,日誌消息可以輪換,這意味著當達到某個閾值時,舊的日誌文件將關閉並打開一個新的日誌文件。

在這裡,我將向您展示如何在 Ubuntu 18.04/20.04 上使用 logrotate 輪換日誌文件。

什麼是日誌輪換?

日誌輪換是通過定期歸檔當前日誌文件並啟動新日誌文件來解決這些問題的過程。 它重命名並可選擇壓縮當前日誌文件,刪除舊日誌文件,並強制日誌系統開始使用新日誌文件。 它通常通過 cron 實用程序自動運行。 通過日誌輪換,您可以

  • 按計劃開始一個新的日誌文件,例如每天、每週或每月
  • 壓縮舊日誌文件以節省磁盤空間
  • 修剪舊檔案,以便您只保留一定數量的舊日誌。
  • 用日期戳重命名舊日誌文件,以便您知道在哪裡查找舊日誌。
  • 在輪換一組日誌之前或之後運行命令。

您可以將日誌輪換視為重命名當前日誌文件並為新日誌條目設置新日誌文件的過程。 輪換日誌文件時,通常會將舊日誌文件複製到其中包含輪換日期的文件中。

1)logrotate的配置文件

在 Ubuntu 18.04 上,logrotate 的配置文件是 /etc/logrotate.conf, 連同任何文件 /etc/logrotate.d主 logrotate.conf 文件指定要輪換的任何默認設置和系統文件。 該文件包含一些由註釋很好地解釋的選項。

cat /etc/logrotate.conf 
# see "man logrotate" for details
# rotate log files weekly
weekly

# use the syslog group by default, since this is the owning group
# of /var/log/syslog.
su root syslog

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp, or btmp -- we'll rotate them here
/var/log/wtmp {
    missingok
    monthly
    create 0664 root utmp
    rotate 1
}

/var/log/btmp {
    missingok
    monthly
    create 0660 root utmp
    rotate 1
}

# system-specific logs may be configured here

的主要選項 對數旋轉 是:

  • 每週: 每週輪換日誌文件一次
  • su 根系統日誌: 將使用特定用戶 (root) 和組 (syslog) 歸檔日誌以防止出現權限問題
  • 旋轉4: 確保保存了文件的四個舊版本。 在刪除之前將給定的日誌旋轉四次,這樣可以保持四個星期的在線日誌。
  • 創建: 舊文件以新名稱保存並創建新文件
  • 壓縮: compress 導致 logrotate 壓縮日誌文件以節省空間。 這是默認使用 gzip 完成的,但您可以指定另一個程序
  • 包括: 這個重要的選項確保目錄的內容 /etc/logrotate.d 已經包括了。 在此目錄中,存在指定如何處理某些單個日誌文件的文件。

中的每個文件 /etc/logrotate.d 用於添加其他設置或覆蓋特定文件的默認設置。 該文件夾還包含您安裝的任何需要日誌輪換的包的 logrotate 配置

# ls -l /etc/logrotate.d
total 40
-rw-r--r-- 1 root root 120 Nov 2 2017 alternatives
-rw-r--r-- 1 root root 442 Oct 23 2017 apache2
-rw-r--r-- 1 root root 126 Nov 20 16:39 apport
-rw-r--r-- 1 root root 173 Apr 20 10:08 apt
-rw-r--r-- 1 root root 112 Nov 2 2017 dpkg
-rw-r--r-- 1 root root 146 Apr 17 17:35 lxd
-rw-r--r-- 1 root root 845 Jan 12 10:57 mysql-server
-rw-r--r-- 1 root root 501 Jan 14 16:19 rsyslog
-rw-r--r-- 1 root root 178 Aug 15 2017 ufw
-rw-r--r-- 1 root root 235 Apr 17 14:53 unattended-upgrades

你可以看到 example apache web 服務器的 logrotate 配置

# cat /etc/logrotate.d/apache2 
/var/log/apache2/*.log {
	daily
	missingok
	rotate 14
	compress
	delaycompress
	notifempty
	create 640 root adm
	sharedscripts
	postrotate
                if invoke-rc.d apache2 status > /dev/null 2>&1; then 
                    invoke-rc.d apache2 reload > /dev/null 2>&1; 
                fi;
	endscript
	prerotate
		if [ -d /etc/logrotate.d/httpd-prerotate ]; then 
			run-parts /etc/logrotate.d/httpd-prerotate; 
		fi; 
	endscript
}

Logrotate 包含一些您可以在上面看到的附加選項:

  • 日常: 基於日輪換日誌
  • 遺漏: 如果日誌丟失,不要引發錯誤
  • 延遲壓縮: 在文件被旋轉之前不要壓縮文件。 這是為了防止守護進程沒有損壞 close 立即記錄日誌文件。
  • 通知空: 日誌文件為空時不要旋轉
  • 創建 640 根管理員: 這將創建具有設置權限、所有者和組的新日誌文件
  • 共享腳本: 如果通配符匹配多個文件,則為所有文件運行任何腳本一次
  • 後旋轉/尾標: 指定一些命令或腳本,這些命令或腳本應該在日誌輪換後執行,直到 endscript 關鍵字。
  • 預旋轉/結束腳本: 作為 postrotate/endscript,它指定應該在日誌輪換開始之前執行的命令或腳本。

您可以通過使用手冊了解有關附加選項的一些信息

man logrotate

2)使用logrotate配置日誌輪換

logrotate 命令通常循環重命名(或輪換)日誌文件; 日誌文件將被重命名為包含數字或日期擴展名,並且將創建一個新的日誌文件來接受系統信息。 如果 logrotate 配置為只保留舊日誌文件的兩個副本,那麼在兩次日誌輪換後,將自動刪除最舊的日誌文件。

通常 logrotate 命令默認安裝在你的 Ubuntu 18.04 上,你可以檢查版本如下

# logrotate --version
logrotate 3.11.0

默認情況下,logrotate 通過執行 shell 腳本每天運行 /etc/cron.daily/logrotate 您將看到其他 cron 文件不包含任何 logrotate 文件

cat /etc/cron.daily/logrotate 
#!/bin/sh

# Clean non existent log file entries from status file
cd /var/lib/logrotate
test -e status || touch status
head -1 status > status.clean
sed 's/"//g' status | while read logfile date
do
    [ -e "$logfile" ] && echo ""$logfile" $date"
done >> status.clean
mv status.clean status

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

如果使用以下命令執行,您可以看到應用程序的 logrotate 配置會做什麼 -d 命令參數

# logrotate -d /etc/logrotate.d/mysql-server 
reading config file /etc/logrotate.d/mysql-server
Reading state from file: /var/lib/logrotate/status
Allocating hash table for state file, size 64 entries

Handling 1 logs

rotating pattern: /var/log/mysql.log /var/log/mysql/*log  after 1 days (7 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/mysql.log
error: skipping "/var/log/mysql.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.
Creating new state
considering log /var/log/mysql/error.log
Creating new state
  Now: 2018-05-22 06:02
  Last rotated at 2018-05-22 06:00
  log does not need rotating (log has been already rotated)

您可以以 root 用戶和非 root 用戶的身份配置日誌輪換。

a) 為已安裝的服務器包設置 logrotation

以 root 用戶身份創建 Logrotate 配置文件 /etc/logrotate.d 每日文件夾。 為了 example,我們將為監控工具supervisor配置日誌輪換。 首先,我們將創建日誌輪換文件,我們將在該文件上指明將存儲日誌的配置文件

# vim /etc/logrotate.d/supervisor
/var/log/supervisor/superviz.log {
        daily
        create 0640 root root
        missingok
        dateext
        rotate 3
        size=1M
        notifempty
        sharedscripts
        mail [email protected]
}

讓我們解釋一些選項:

  • 日期文本: 使用日期作為舊版本日誌文件的擴展名
  • 尺寸: 記錄增長到大於此處指定大小的文件
  • 郵件: 指示 logrotate 在覆蓋之前將其內容通過電子郵件發送到指定地址。 你必須有一個工作的郵件服務器

現在我們可以通過在調試模式下調用 logrotate 來測試配置,該模式指向包含我們文件夾的主配置。 該命令將顯示一些信息,但我們只會對有關我們的配置的信息進行排序

# logrotate /etc/logrotate.conf --debug
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file alternatives
reading config file apache2
reading config file apport
reading config file apt
reading config file dpkg
reading config file lxd
reading config file mysql-server
reading config file rsyslog
reading config file supervisor
reading config file ufw
reading config file unattended-upgrades
Reading state from file: /var/lib/logrotate/status
...
...
rotating pattern: /var/log/supervisor/supervisord.log  1048576 bytes (3 rotations)
empty log files are not rotated, old logs mailed to [email protected]
switching euid to 0 and egid to 106
considering log /var/log/supervisor/supervisord.log
Creating new state
  Now: 2018-05-22 08:16
  Last rotated at 2018-05-22 08:00
  log does not need rotating (log size is below the 'size' threshold)
switching euid to 0 and egid to 0
....
....

您可以看到我們的配置還不需要旋轉。 這是因為它尚未驗證的條件大小。 一旦這個命令運行沒有任何錯誤,就意味著配置看起來不錯。

b) 為自定義應用程序設置日誌輪換

您可以為生成日誌並以非 root 用戶身份運行的自定義應用程序配置日誌輪換。 默認情況下,logrotate 每天運行,因此,如果我們需要每小時運行我們的應用程序,我們將在默認文件夾之外創建 logrotate 配置。

讓我們來一個 example 通過為discord配置日誌輪換。 我們將創建一個包含主要 logrotate 配置文件和日誌文件文件夾的個人文件夾。 此應用程序不了解日誌輪換,因此 logrotate 將通過使用複制和截斷實現來處理此問題

$ vim apps/logrotate.conf
/home/alain/apps/logs/discord.log {
        hourly
        copytruncate
        missingok
        dateext
        rotate 10
        compress
}

我們使用了新選項 複製截斷 在創建副本後截斷舊日誌文件,而不是移動舊文件並創建新文件。 這對於無法告知的服務很有用 close 他們的日誌文件。

我們可以測試我們的配置,但我們需要指定一個狀態文件。 這個文件記錄了 logrotate 上次運行時看到和做的事情,以便它知道下次運行時要做什麼。 請注意,我們以非 root 用戶身份運行命令

$ logrotate /home/alain/apps/logrotate.conf --state /home/alain/apps/logrotate-state --verbose
reading config file /home/alain/apps/logrotate.conf
Reading state from file: /home/alain/apps/logrotate-state
Allocating hash table for state file, size 64 entries

Handling 1 logs

rotating pattern: /home/alain/apps/logs/discord.log  hourly (10 rotations)
empty log files are rotated, old logs are removed
considering log /home/alain/apps/logs/discord.log
Creating new state
  Now: 2018-05-22 10:09
  Last rotated at 2018-05-22 10:00
  log does not need rotating (log has been already rotated)

如果您在幾個小時後嘗試相同的命令,您可以在輸出中看到一些附加信息,例如截斷和壓縮信息

logrotate /home/alain/apps/logrotate.conf --state /home/alain/apps/logrotate-state --verbose
reading config file /home/alain/apps/logrotate.conf
Reading state from file: /home/alain/apps/logrotate-state
Allocating hash table for state file, size 64 entries
Creating new state

Handling 1 logs

rotating pattern: /home/alain/apps/logs/discord.log  hourly (10 rotations)
empty log files are rotated, old logs mailed to [email protected]
considering log /home/alain/apps/logs/discord.log
  Now: 2018-05-22 22:52
  Last rotated at 2018-05-22 10:23
  log needs rotating
rotating log /home/alain/apps/logs/discord.log, log->rotateCount is 10
dateext suffix '-2018052222'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
copying /home/alain/apps/logs/discord.log to /home/alain/apps/logs/discord.log-2018052222
truncating /home/alain/apps/logs/discord.log
compressing log with: /bin/gzip

您必須確保 logrotate 配置由匹配日誌文件的文件 glob 定義,後跟括在花括號內的一系列指令。 如果在附加到日誌文件名稱的節中未指定選項,則來自 /etc/logrotate.conf 優先。 已輪換的日誌文件不會存儲在任何地方; 他們剛剛消失,所以你應該考慮採取措施。

另請閱讀:

  • 如何在 Ubuntu 18.04 上檢查 Cron 日誌
  • lnav – 從 Linux 終端查看和分析日誌文件的工具
  • 如何使用 Systemd journalctl 命令管理日誌