Linux 上使用 Linux Shell 腳本自動化按天分割、壓縮(延遲壓縮)和定期清理日誌文件

2019-02-26 10:10:54
最近 Hgh這邊有一個需求,需要對Linux服務器上的日誌進行相應地自動化處理:
1) 定期清理:當分區的可使用空間超過一個預先設定好的閾值(如當分區的可使用空間超過 80 % 時)就自動清 理日誌,清理週期是一天一次;
2) 按天分割:有的日誌文件如 access.log 會不斷地增長,現在需要對其進行分割操作(假設今天的日期是 2019 年 1 月 25 日,當時間到達 2019 年 1 月 26 日 0 點 0 分時,自動分割出一個 access.log.20190125 的日誌文 件;
3) 壓縮:對 access.log.20190125 這樣的日誌文件進行壓縮,即生成壓縮包 access.log.20190125.tar.gz 並刪除日誌文件 access.log.20190125 ;
4) 延遲壓縮:有的開發可能需要查看最近幾天的日誌,爲了方便開發查看日誌,可對最近幾天的日誌文件進行延遲壓縮的操作(假設今天的日期是 2019 年 1 月 25 日,根據開發的要求暫時不壓縮最近一天的日誌,則當時間到達 2019 年 1 月 26 日 0 點 0 分時,壓縮的是 2019 年 1 月 24 日的日誌文件 access.log.20190124 ,過了 24 小時以後再壓縮 access.log.20190125 )。

部署:
1 、編寫腳本,在命令行界面輸入:

[root@host ~]# vi /root/log.sh
鍵入小寫字母 i ,進入編輯模式,將 “ 附錄 ” 中的 log.sh 複製粘貼進去。

按一次 ESC 鍵退出編輯模式,然後鍵入 “ :wq ” 保存並退出。

2 、創建並修改配置文件,在命令行界面輸入:

[root@host ~]# vi /root/log.config
鍵入小寫字母 i ,進入編輯模式,將 “ 附錄 ” 中的 log.config 複製粘貼進去(請根據實際需要修改相應地配置)。

按一次 ESC 鍵退出編輯模式,然後鍵入 “ :wq ” 保存並退出。

3 、爲上述腳本賦予可執行權限,並創建日誌文件:

[root@host ~]# chmod +x /root/log.sh
[root@host ~]# touch /root/log.log
4 、讓上述腳本每天凌晨 0 點 0 分自動運行一次,在命令行界面輸入:

[root@host ~]# echo "0 0 * sh /root/log.sh" >> /var/spool/cron/root
至此,部署完成。

應用舉例:
Hgh將會通過應用舉例的方式來說明這個腳本具體是如何使用的。

舉例用的操作系統版本號如下所示:

[root@host ~]# cat /etc/redhat-release
CentOS Linux release 7.0.1406 (Core)
[root@host ~]#
簡單使用和定期清理日誌:
1 、先創建一些日誌文件用來模擬生產環境:

[root@host ~]# mkdir -p /www/log/applog/
[root@host ~]# mkdir -p /www/log/accesslog/
[root@host ~]# echo 123 > /www/log/applog/www.test.com.log
[root@host ~]# echo 123 > /www/log/applog/www.test.net.log
[root@host ~]# echo 123 > /www/log/accesslog/www.test.com.log
[root@host ~]# echo 123 > /www/log/accesslog/www.test.net.log.20190128.00
[root@host ~]# echo 123 > /www/log/accesslog/www.test.net.log.20190128.01
[root@host ~]# echo 123 > /www/log/accesslog/www.test.net.log.20190128.02
現在使用 tree 命令來看一下日誌文件夾的目錄結構:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]#
2 、修改配置文件,具體配置如下所示:

[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz
[root@host ~]#
這裏解釋說明一下上述配置的作用:

mount :設置日誌文件所在的掛載點,具體掛載點請用 df -h 命令查看;
mount_used_size_percent :設置該掛載點最多可以使用多少空間,單位是百分比;
log_dir :設置日誌文件所在的文件夾,用於自動清理日誌文件(從文件修改時間是最舊的日誌文件開始刪除,包括子文件夾下的日誌文件),直到上述掛載點的可使用空間最多不超過 mount_used_size_percent 這個百分比爲止(除非日誌文件已經全部刪除完畢);
log_format_regex :是一串正則表達式,用於自定義待刪除的日誌文件格式,防止誤刪除。
和上述配置的舉例、注意事項:

( 1 )log_format_regex 舉例和注意事項:

如待刪除的日誌文件均爲壓縮格式,則這麼配置即可(其中 ” \ ” 是轉義字符,” | ” 是 ” 或 ” ):log_format_regex=(.tar|.gz|.tar.gz|.bz2|.tar.bz2|.bz|.tar.bz|.Z|.tar.Z|.tgz|.tar.tgz|.zip|.lha|.rar)$ ;
注意:請不要把 .log 這個關鍵字寫入進去,因爲很多正在寫入的日誌文件都是以 xxx.log 命名的,這些文件是不能匹配到並刪除的。
和上述配置的取值範圍:

mount :該值必須配置且僅允許配置一次;
mount_used_size_percent :該值必須配置且僅允許配置一次,取值範圍在 50 ≤ x ≤ 85 之間;
log_dir :該值必須配置且允許配置多次,如果文件夾不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行;
log_format_regex :該值必須配置且僅允許配置一次。
3 、現在我們來看看這個腳本是如何運行的,如果直接運行會彈出如下提示:

[root@host ~]# sh log.sh
Please run the script at 0 a.m.
[root@host ~]#
因爲該腳本最主要的一個功能就是自動化按天分割日誌文件,爲了讓該功能能夠準確地運行,建議您在每天 0 點 0 分的時候才執行該腳本(或者說在每天 0 點 0 分的時候才執行 “ 按天分割日誌 ” 的操作),所以 這裏限制了該腳本的運行時間(該腳本只允許在每天 0 點 0 分至 0 點 59 分之間運行)。

那如何調試腳本呢?您需要這麼運行:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
即開啓調試模式,強行讓腳本執行起來(請不用在生產環境上調試,以免誤刪除重要文件)。

同時,log.config 配置文件和 log.log 該腳本的日誌文件默認是放置在 /root/ 目錄下的,如果您想自定義路徑,可以這麼運行腳本:

[root@host ~]# sh log.sh config_file=/ricky/log.config
config file ( /ricky/log.config ) not found !
[root@host ~]#
[root@host ~]# sh log.sh log_file=/ricky/log.log
log file ( /ricky/log.log ) not found !
[root@host ~]#
[root@host ~]# sh log.sh config_file=/ricky/log.config log_file=/ricky/log.log
config file ( /ricky/log.config ) not found !
[root@host ~]#
[root@host ~]# sh log.sh log_file=/ricky/log.log config_file=/ricky/log.config
config file ( /ricky/log.config ) not found !
[root@host ~]#
[root@host ~]# sh log.sh log_file=/ricky/log.log config_file=/ricky/log.config debug_mode=yes
config file ( /ricky/log.config ) not found !
[root@host ~]#
如上所示,腳本會自動判斷 config_file 和 log_file 這兩個文件是否存在;如果這兩個文件不存在,腳本會終止運行。

4 、此時 /www/log/ 的目錄結構和 log.config 配置文件如下所示:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]# cat /root/log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz
[root@host ~]#
執行該腳本:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
腳本執行完畢後 /www/log/ 的目錄結構和 log.log 日誌文件如下所示:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]# cat /root/log.log
2019-01-29 09:35 - debug_mode is enabled ! Do NOT use in production environment !
2019-01-29 09:35 - Delete all the log files is completed , but did not reach the 50 % used precent !
2019-01-29 09:35 - === gz log ===
[root@host ~]#
此時 /www/log/ 目錄結構無任何變化,因爲我們在 log.config 配置文件裏面配置了這兩句:

log_dir=/www/log
log_format_regex=.tar.gz
所以腳本只會在 /www/log/ 目錄(包括子目錄)裏刪除文件名帶有 tar.gz 字樣的文件,而 /www/log 目錄下並無帶有 tar.gz 字樣的文件。

此時 log.log 日誌文件裏還記錄了一條日誌:

2019-01-29 09:35 - Delete all the log files is completed , but did not reach the 50 % used precent !
該日誌的意思是說所有的日誌文件已經刪除完畢了(因爲確實也不存在文件名帶有 tar.gz 字樣的文件了),但是掛載點 /www 的已使用空間依然超過了 50 % ,df -h 命令的執行結果如下所示:

[root@host ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 369M 3.6G 10% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda2 10G 6.5G 3.5G 66% /
/dev/sda5 48G 30G 18G 63% /www
/dev/sda1 197M 107M 90M 55% /boot
[root@host ~]#
5 、現在我們多創建幾個文件再測試一次:

[root@host ~]# echo 456 > /www/log/accesslog/www.test.net.log.tar
[root@host ~]# echo 456 > /www/log/accesslog/www.test.net.log.tar.gz
[root@host ~]# echo 456 > /www/log/applog/www.test.net.log.tar
[root@host ~]# echo 456 > /www/log/applog/www.test.net.log.tar.gz
[root@host ~]# echo 456 > /www/log/applog/www.test.net.tar.gz.log
[root@host ~]#
[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ ├── www.test.net.log.20190128.02
│ ├── www.test.net.log.tar
│ └── www.test.net.log.tar.gz
└── applog
├── www.test.com.log
├── www.test.net.log
├── www.test.net.log.tar
├── www.test.net.log.tar.gz
└── www.test.net.tar.gz.log

2 directories, 11 files
[root@host ~]#
執行該腳本:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
查看 /www/log/ 目錄我們可以發現,凡是文件名帶有 tar.gz 字樣的文件都刪除掉了:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ ├── www.test.net.log.20190128.02
│ └── www.test.net.log.tar
└── applog
├── www.test.com.log
├── www.test.net.log
└── www.test.net.log.tar

2 directories, 8 files
[root@host ~]#
6 、如果您只想刪除以 .tar.gz 結尾的文件,只需要這麼配置:

[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz$
[root@host ~]#
加一個正則表達式裏的 $ 符號即可(即只匹配以 .tar.gz 結尾的文件),這樣文件 www.test.net.tar.gz.log 就不會被刪除了(親測有效)。

7 、log_dir 允許配置多個值,如:

[root@host ~]# cat /root/log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log/accesslog
log_dir=/www/log/applog
log_dir=/tmp/applog
log_format_regex=.tar.gz
[root@host ~]#
腳本會預先判斷這些文件夾是否存在,如果其中一個文件夾是不存在的,腳本會將錯誤信息寫入到日誌文件 log.log 並終止運行。具體報錯信息如下所示:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]#
[root@host ~]# cat log.log
2019-01-29 15:17 - debug_mode is enabled ! Do NOT use in production environment !
2019-01-29 15:17 - log_dir /tmp/applog does not exist !
[root@host ~]#
按天分割日誌:
1 、修改配置文件,具體配置如下所示:

[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

cut_log=/www/log/accesslog/www.test.com.log
[root@host ~]#
這裏解釋說明一下上述配置的作用:

cut_log :設置需要進行按天分割的日誌文件的文件路徑。
和上述配置的舉例:

( 1 )cut_log 舉例:

比如:cut_log=/www/accesslog/www.test.com/access.log ,假設今天的日期是 2019 年 1 月 29 日,那麼到了 2019 年 1 月 30 日凌晨 0 點 0 分會分卷一份 access.log.20190129 出來。
允許設置多條,如:
cut_log=/www/accesslog/www.test.com/access.log
cut_log=/www/accesslog/www.test.net/access.log
也可以不設置,如:
cut_log=
和上述配置的取值範圍:

cut_log :該值可不配置且允許配置多次,日誌文件路徑必須是絕對路徑,如果文件不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行。
2 、此時 /www/log/ 的目錄結構和 log.config 配置文件如下所示:

[root@host ~]# tree /www/log
/www/log
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]#
[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

cut_log=/www/log/accesslog/www.test.com.log
cut_log=/www/log/applog/www.test.com.log
[root@host ~]#
當前兩個日誌文件 /www/log/accesslog/www.test.com.log 和 /www/log/applog/www.test.com.log 的內容如下所示:

[root@host ~]# cat /www/log/accesslog/www.test.com.log
123
[root@host ~]# cat /www/log/applog/www.test.com.log
123
[root@host ~]#
執行完腳本以後會發現多出了兩個日誌文件 /www/log/accesslog/www.test.com.log.20190129 和 /www/log/applog/www.test.com.log.20190129(假設執行腳本的時間是 2019 年 1 月 30 日 0 點 0 分):

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]#
[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.com.log.20190129
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
├── www.test.com.log.20190129
└── www.test.net.log

2 directories, 8 files
[root@host ~]#
同時原日誌文件已經被清空:

[root@host ~]# cat /www/log/accesslog/www.test.com.log

[root@host ~]# cat /www/log/applog/www.test.com.log

[root@host ~]# cat /www/log/accesslog/www.test.com.log.20190129
123
[root@host ~]# cat /www/log/applog/www.test.com.log.20190129
123
[root@host ~]#
3 、腳本會預先判斷這些文件是否存在,如果其中一個文件是不存在的,腳本會將錯誤信息寫入到日誌文件 log.log 並終止運行。此時 /www/log/ 的目錄結構和 log.config 配置文件如下所示:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]#
[root@host ~]#
[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

cut_log=/www/log/accesslog/www.test.com.log
cut_log=/www/log/applog/www.test.com.log123
[root@host ~]#
具體報錯信息如下所示:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]# cat log.log
2019-01-31 09:18 - debug_mode is enabled ! Do NOT use in production environment !
2019-01-31 09:18 - log_file /www/log/applog/www.test.com.log123 does not exist !
[root@host ~]#
壓縮日誌:
1 、修改配置文件,具體配置如下所示:

[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

gz_log=/www/log/applog/www.test.com.log
gz_delay_day=
[root@host ~]#
這裏解釋說明一下上述配置的作用:

gz_log :設置需要進行壓縮的日誌文件(支持自定義日期格式和模糊匹配)的文件路徑;
gz_delay_day :設置延遲壓縮的天數。
和上述配置的舉例:

( 1 )gz_log 舉例:

支持自定義日期格式,其中:
” %YYYY ” 是年
” %MMMM ” 是月
” %DDDD ” 是日;
支持模糊匹配:比如文件 /tmp/app.log.2019-01-30-00 和 /tmp/app.log.2019-01-30-01 這兩個文件 ,只需要這麼設置 gz_log=/tmp/app.log.%YYYY-%MMMM-%DDDD 即可自動將上述兩個文件一同打入壓縮包 /tmp/app.log.2019-01-30.tar.gz 。
( 2 )gz_delay_day 舉例:

支持延遲壓縮日誌文件:有的開發可能需要查看最近幾天的日誌,壓縮後就不容易直接查看了;爲了方便開發查看最近幾天的日誌,那麼每天就不能壓縮昨天的日誌了,而是每天壓縮前天或者大前天的日誌,這樣開發就還可以查看昨天或者前天的日誌。比如:gz_delay_day=1 表示壓縮昨天的日誌,gz_delay_day=2 表示壓縮前天的日誌,gz_delay_day=3 表示壓縮大前天的日誌。
和上述配置的取值範圍:

gz_log :該值可不配置且允許配置多次,日誌文件路徑必須是絕對路徑,如果文件不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行;
gz_delay_day :該值可不配置且僅允許配置一次,取值範圍是 x ≥ 1 ,默認值是 1 。
2 、現在打算對日誌文件 /www/log/applog/www.test.com.log 進行壓縮,此時 /www/log/ 的目錄結構和 log.config 配置文件如下所示:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log
└── www.test.net.log

2 directories, 6 files
[root@host ~]#
[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

gz_log=/www/log/applog/www.test.com.log
gz_delay_day=
[root@host ~]#
當前日誌文件 /www/log/applog/www.test.com.log 的內容如下所示:

[root@host ~]# cat /www/log/applog/www.test.com.log
123
[root@host ~]#
執行完腳本以後會發現多出了一個壓縮包 www.test.com.log.tar.gz ,同時原日誌文件 www.test.com.log 已經被刪除:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
├── www.test.com.log.tar.gz
└── www.test.net.log

2 directories, 6 files
[root@host ~]#
我們解壓看看:

[root@host ~]# mkdir /tmp/log/
[root@host ~]# mv /www/log/applog/www.test.com.log.tar.gz /tmp/log/
[root@host ~]# cd /tmp/log/
[root@host log]# tar zxf www.test.com.log.tar.gz
[root@host log]# ls
www.test.com.log www.test.com.log.tar.gz
[root@host log]#
[root@host log]# cat www.test.com.log
123
[root@host log]#
可以看到日誌文件 www.test.com.log 就是原來那個。

3 、我們現在來看看自定義日期格式和模糊匹配的使用,現在我們要壓縮:

/www/log/accesslog/www.test.net.log.20190128.00
/www/log/accesslog/www.test.net.log.20190128.01
/www/log/accesslog/www.test.net.log.20190128.02
這三個日誌文件,此時 /www/log/ 的目錄結構和 log.config 配置文件如下所示:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.net.log.20190128.00
│ ├── www.test.net.log.20190128.01
│ └── www.test.net.log.20190128.02
└── applog
└── www.test.net.log

2 directories, 5 files
[root@host ~]#
[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

gz_log=/www/log/accesslog/www.test.net.log.%YYYY%MMMM%DDDD
gz_delay_day=3
[root@host ~]#
假設今天的日期是 2019 年 1 月 31 日,那麼 30 日是昨天,29 日是前天,28 日是大前天,所以 gz_delay_day 的值爲 3 。

執行完腳本以後會發現多出了一個壓縮包 www.test.net.log.20190128.tar.gz ,同時三個日誌文件已經被刪除:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ └── www.test.net.log.20190128.tar.gz
└── applog
└── www.test.net.log

2 directories, 3 files
[root@host ~]#
我們同樣解壓出來看看:

[root@host ~]# mkdir /tmp/log_20190128/
[root@host ~]# mv /www/log/accesslog/www.test.net.log.20190128.tar.gz /tmp/log_20190128/
[root@host ~]# cd /tmp/log_20190128/
[root@host log_20190128]# tar zxf www.test.net.log.20190128.tar.gz
[root@host log_20190128]# ls
www.test.net.log.20190128.00 www.test.net.log.20190128.01 www.test.net.log.20190128.02 www.test.net.log.20190128.tar.gz
[root@host log_20190128]#
可以看到三個日誌文件都在壓縮包中。

4 、其他自定義日期格式的例子,假設有的程序已經能夠每小時自動生成一個日誌文件,例如:

/www/log/accesslog/www.test.net.log.2019-01-30-00
/www/log/accesslog/www.test.net.log.2019-01-30-01
/www/log/accesslog/www.test.net.log.2019-01-30-02
……
/www/log/accesslog/www.test.net.log.2019-01-30-23
那麼只需要這麼設置即可:

gz_log=/www/log/accesslog/www.test.net.log.%YYYY-%MMMM-%DDDD
這樣,上述 24 個日誌文件將會在 2019 年 1 月 31 日 0 點 0 分統一壓縮進壓縮包 www.test.net.log.2019-01-30.tar.gz ,然後再刪除上述 24 個日誌文件。

按天分割和壓縮(延遲壓縮)的功能是可以互相獨立使用的;當然也可以結合起來使用,具體請看下方的 “ 綜合應用 ” 。

綜合應用:
現在有如下所示的四個日誌文件:

[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ └── www.test.com.log.20190129
└── applog
├── www.test.net.log
└── www.test.net.log.20190129

2 directories, 4 files
[root@host ~]#
現在的需求是:

( 1 )當 /www 的掛載點的可使用空間超過 50 % 時,自動刪除 /www/log/ 目錄下(包括子目錄)文件名帶有 tar.gz 字樣的文件,以釋放硬盤空間。

( 2 )假設今天的日期是 2019 年 1 月 30 日,當時間走到 2019 年 1 月 31 日 0 點 0 分時,需要對日誌文件做一個分割:

/www/log/accesslog/www.test.com.log → /www/log/accesslog/www.test.com.log.20190130
/www/log/applog/www.test.net.log → /www/log/applog/www.test.net.log.20190130
( 3 )然後再對前天的日誌文件進行一個壓縮:

/www/log/accesslog/www.test.com.log.20190129 → /www/log/accesslog/www.test.com.log.20190129.tar.gz
/www/log/applog/www.test.net.log.20190129 → /www/log/applog/www.test.net.log.20190129.tar.gz
那麼,log.config 配置文件只需要這麼配置即可:

[root@host ~]# cat log.config
mount=/www
mount_used_size_percent=50

log_dir=/www/log
log_format_regex=.tar.gz

cut_log=/www/log/accesslog/www.test.com.log
cut_log=/www/log/applog/www.test.net.log

gz_log=/www/log/accesslog/www.test.com.log.%YYYY%MMMM%DDDD
gz_log=/www/log/applog/www.test.net.log.%YYYY%MMMM%DDDD
gz_delay_day=2
[root@host ~]#
執行腳本後,結果如下所示:

[root@host ~]# sh log.sh debug_mode=yes
debug_mode is enabled ! Do NOT use in production environment !
[root@host ~]#
[root@host ~]# tree /www/log/
/www/log/
├── accesslog
│ ├── www.test.com.log
│ ├── www.test.com.log.20190129.tar.gz
│ └── www.test.com.log.20190130
└── applog
├── www.test.net.log
├── www.test.net.log.20190129.tar.gz
└── www.test.net.log.20190130

2 directories, 6 files
[root@host ~]#
至此,該腳本介紹完畢。

附錄:
1 、log.sh :
#!/bin/bash

config_file="/root/log.config"
log_file="/root/log.log"
debug_mode="no"

for i in $* ; do
if [[ "$i" =~ "config_file=" ]] ; then
config_file=echo $i | awk -F'=' '{print $2}'
elif [[ "$i" =~ "log_file=" ]] ; then
log_file=echo $i | awk -F'=' '{print $2}'
elif [[ "$i" =~ "debug_mode=" ]] ; then
debug_mode=echo $i | awk -F'=' '{print $2}'
fi
done

if [ ! -f "$config_file" ] ; then
echo "config file ( $config_file ) not found !"
exit
fi

if [ ! -f "$log_file" ] ; then
echo "log file ( $log_file ) not found !"
exit
fi

if [ "$debug_mode" == "no" -a "date '+%H'" != "00" ] ; then
echo Please run the script at 0 a.m.
exit
elif [ "$debug_mode" != "no" ] ; then
debug_mode="yes"
echo debug_mode is enabled ! Do NOT use in production environment !
echo $(date "+%F %H:%M") - debug_mode is enabled ! Do NOT use in production environment ! >> $log_file
fi

#1. get mount
config_file_flag=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep -c "mount="
if [ $config_file_flag == 1 ] ; then
mount=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "mount=" | awk -F'=' '{print $2}'
elif [ $config_file_flag == 0 ] ; then
echo $(date "+%F %H:%M") - "mount parameter is not found !" >> $log_file
exit
else
echo $(date "+%F %H:%M") - "mount parameter is too many !" >> $log_file
exit
fi

if [ df -h | grep "$mount" | awk -F' ' '{print $5}' | awk -F'%' '{print $1}' | grep -c '^[[:digit:]]*$' == 0 ] ; then
echo $(date "+%F %H:%M") - "mount parameter is error !" >> $log_file
exit
fi

#2. get mount_used_size_percent
config_file_flag=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep -c "mount_used_size_percent="
if [ $config_file_flag == 1 ] ; then
mount_used_size_percent=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "mount_used_size_percent=" | awk -F'=' '{print $2}'
elif [ $config_file_flag == 0 ] ; then
echo $(date "+%F %H:%M") - "mount_used_size_percent parameter is not found !" >> $log_file
exit
else
echo $(date "+%F %H:%M") - "mount_used_size_percent parameter is too many !" >> $log_file
exit
fi

if [ echo $mount_used_size_percent | grep -c '^[[:digit:]]*$' == 0 ] ; then
echo $(date "+%F %H:%M") - "mount_used_size_percent parameter is not number !" >> $log_file
exit
fi

if [ $mount_used_size_percent -lt 50 ] ; then
echo $(date "+%F %H:%M") - "mount_used_size_percent parameter requires more than or equal to 50 !" >> $log_file
exit
elif [ $mount_used_size_percent -gt 85 ] ; then
echo $(date "+%F %H:%M") - "mount_used_size_percent parameter requires less than or equal to 85 !" >> $log_file
exit
fi

#3. get log_format_regex
config_file_flag=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep -c "log_format_regex="
if [ $config_file_flag == 1 ] ; then
log_format_regex=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "log_format_regex=" | awk -F'=' '{print $2}'
elif [ $config_file_flag == 0 ] ; then
echo $(date "+%F %H:%M") - "log_format_regex parameter is not found !" >> $log_file
exit
else
echo $(date "+%F %H:%M") - "log_format_regex parameter is too many !" >> $log_file
exit
fi

#4. get log_dir_list
config_file_flag=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep -c "log_dir="
if [ $config_file_flag -ge 1 ] ; then
log_dir_list=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "log_dir=" | awk -F'=' '{print $2}'
elif [ $config_file_flag == 0 ] ; then
echo $(date "+%F %H:%M") - "log_dir parameter is not found !" >> $log_file
exit
fi

for log_dir in $log_dir_list ; do
if [ ! -d "$log_dir" ] ; then
echo $(date "+%F %H:%M") - "log_dir $log_dir does not exist !" >> $log_file
exit
fi
done

#5. delete log file
while [ df -h | grep "$mount" | awk -F' ' '{print $5}' | awk -F'%' '{print $1}' -gt $mount_used_size_percent ] ; do
while_flag=""
for log_dir in $log_dir_list ; do
if [ find $log_dir -type f | grep -cE $log_format_regex -gt 0 ] ; then
find $log_dir -type f | grep -E $log_format_regex | xargs ls -ta | tail -1 | xargs rm -f
while_flag=$while_flag"1"
else
while_flag=$while_flag"0"
fi
done
if [ echo $while_flag | grep -c 1 == 0 ] ; then
echo $(date "+%F %H:%M") - "Delete all the log files is completed , but did not reach the $mount_used_size_percent % used precent !" >> $log_file
break
fi
done

#6. get cut_log_list
cut_log_list=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "cut_log=" | awk -F'=' '{print $2}'

for cut_log in $cut_log_list ; do
if [ ! -f "$cut_log" ] ; then
echo $(date "+%F %H:%M") - "cut_log $cut_log does not exist !" >> $log_file
exit
fi
done

#7. cut log
yesterday=$(date -d "$(date) -1 day" +%Y%m%d)
for cut_log in $cut_log_list ; do
cp $cut_log $cut_log.$yesterday && echo > $cut_log
done

#8. get gz_log_list
config_file_flag=cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep -c "gz_delay_day="
if [ $config_file_flag == 0 -o $config_file_flag == 1 ] ; then

if [ $config_file_flag == 1 ] ; then
        gz_delay_day=`cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "gz_delay_day=" | awk -F'=' '{print $2}'`
elif [ $config_file_flag == 0 ] ; then
        gz_delay_day=1
fi

if [ `echo $gz_delay_day | grep -c '^[[:digit:]]*$'` == 0 ] ; then
        echo $(date "+%F %H:%M") - "gz_delay_day parameter is not number !" >> $log_file
        exit
fi

if [ $gz_delay_day -lt 1 ] ; then
        echo $(date "+%F %H:%M") - "gz_delay_day parameter requires more than or equal to 1 !" >> $log_file
        exit
fi

gz_log_list=`cat $config_file | grep -v "#" | sed "s# ##g" | grep -vE "=$" | grep "gz_log=" | awk -F'=' '{print $2}'`
date_year=`date -d "$(date) - ${gz_delay_day} day" +%Y`
date_month=`date -d "$(date) - ${gz_delay_day} day" +%m`
date_day=`date -d "$(date) - ${gz_delay_day} day" +%d`

for gz_log in $gz_log_list ; do
        gz_log=`echo $gz_log | sed "s#%YYYY#$date_year#g" | sed "s#%MMMM#$date_month#g" | sed "s#%DDDD#$date_day#g"`
        if [ `ls "$gz_log"* | grep -v "${gz_log}.tar.gz" 2>/dev/null | wc -l` == 0 ] ; then
                echo $(date "+%F %H:%M") - "gz_log $gz_log does not exist !" >> $log_file
                exit
        fi
done

elif [ $config_file_flag -gt 1 ] ; then
echo $(date "+%F %H:%M") - "gz_delay_day parameter is too many !" >> $log_file
exit
fi

#9. gz log
echo $(date "+%F %H:%M") - "=== gz log ===" >> $log_file
for gz_log in $gz_log_list ; do
gz_log=echo $gz_log | sed "s#%YYYY#$date_year#g" | sed "s#%MMMM#$date_month#g" | sed "s#%DDDD#$date_day#g"
cd dirname ${gz_log}
echo dirname ${gz_log}" :" >> $log_file
log_filename=basename ${gz_log}
tar zcvf ${log_filename}.tar.gz --exclude=.tar.gz ${log_filename} >> $log_file
ls ${log_filename}* | grep -v "${log_filename}.tar.gz" | xargs rm -f
done
echo "===========================" >> $log_file
2 、log.config :

mount:設置日誌文件所在的掛載點,如:mount=/www ,具體掛載點請用 df -h 命令查看。
mount 取值範圍:該值必須配置且僅允許配置一次。
mount_used_size_percent:設置該掛載點最多可以使用多少空間,單位是百分比。
mount_used_size_percent 取值範圍:該值必須配置且僅允許配置一次,取值範圍在 50 ≤ x ≤ 85 之間。
mount=
mount_used_size_percent=

log_dir:設置日誌文件所在的文件夾,如:log_dir=/www/accesslog ,用於自動清理日誌文件(從文件修改時間是最舊的日誌文件開始刪除,包括子文件夾下的日誌文件),
直到上述掛載點的可使用空間最多不超過 mount_used_size_percent 這個百分比爲止(除非日誌文件已經全部刪除完畢)。
log_dir 取值範圍:該值必須配置且允許配置多次,如果文件夾不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行。
允許設置多條,如:
log_dir=/www/accesslog
log_dir=/www/applog
log_dir=

log_format_regex:是一串正則表達式,用於自定義待刪除的日誌文件格式,防止誤刪除。
log_format_regex 取值範圍:該值必須配置且僅允許配置一次。
1 、如待刪除的日誌文件均爲壓縮格式,則這麼配置即可(其中 ” \ ” 是轉義字符,” | ” 是 ” 或 ” ):
log_format_regex=(.tar|.gz|.tar.gz|.bz2|.tar.bz2|.bz|.tar.bz|.Z|.tar.Z|.tgz|.tar.tgz|.zip|.lha|.rar)$ ;
2 、注意:請不要把 .log 這個關鍵字寫入進去,因爲很多正在寫入的日誌文件都是以 xxx.log 命名的,這些文件是不能匹配到並刪除的。
log_format_regex=

cut_log:設置需要進行按天分割的日誌文件的文件路徑。
cut_log 的取值範圍:該值可不配置且允許配置多次,日誌文件路徑必須是絕對路徑,如果文件不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行。
1 、比如:cut_log=/www/accesslog/www.test.com/access.log ,假設今天的日期是 2019 年 1 月 29 日,那麼到了 2019 年 1 月 30 日凌晨 0 點 0 分會分卷一份 access.log.20190129 出來。
2 、允許設置多條,如:
cut_log=/www/accesslog/www.test.com/access.log
cut_log=/www/accesslog/www.test.net/access.log
3 、也可以不設置,如:
cut_log=
cut_log=

gz_log:設置需要進行壓縮的日誌文件(支持自定義日期格式和模糊匹配)的文件路徑。
gz_log 的取值範圍:該值可不配置且允許配置多次,日誌文件路徑必須是絕對路徑,如果文件不存在會將錯誤信息寫入到日誌文件 log.log 並終止運行。
1 、支持自定義日期格式,其中:
" %YYYY " 是年
" %MMMM " 是月
" %DDDD " 是日
2 、支持模糊匹配:
比如文件 /tmp/app.log.2019-01-30-00 和 /tmp/app.log.2019-01-30-01 這兩個文件 ,
只需要這麼設置 gz_log=/tmp/app.log.%YYYY-%MMMM-%DDDD 即可自動將上述兩個文件一同打入壓縮包 /tmp/app.log.2019-01-30.tar.gz 。
gz_delay_day:設置延遲壓縮的天數。
gz_delay_day 的取值範圍:該值可不配置且僅允許配置一次,取值範圍是 x ≥ 1 ,默認值是 1 。
1 、支持延遲壓縮日誌文件:有的開發可能需要查看最近幾天的日誌,壓縮後就不容易直接查看了;
爲了方便開發查看最近幾天的日誌,那麼每天就不能壓縮昨天的日誌了,而是每天壓縮前天或者大前天的日誌,這樣開發就還可以查看昨天或者前天的日誌。
比如:gz_delay_day=1 表示壓縮昨天的日誌,gz_delay_day=2 表示壓縮前天的日誌,gz_delay_day=3 表示壓縮大前天的日誌。
gz_log=
gz_delay_day=

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章