
#!/bin/sh
# https://github.com/eyjian/mooon/blob/master/mooon/shell/log_rotater.sh
# Writed by yijian on 2012/7/22
#
# Linux自帶的工具logrotate使用稍複雜,但功能強大
# 本腳本功能:
# 1) 實作一個通用的按大小的日志滾動
# 2) 要求日志檔案擴充名為“.log”,否則請稍修改代碼
# 3) 支援處理多個目錄下的日志檔案,如果需要使用這個功能,
# 必須啟用dirs_list參數
# 為何要寫一個這樣的東東?
# 答:因為在日常中,經常發現程式輸出重定向,
# 或腳本的輸出,如果不處理的話,就可能導緻
# 單個檔案過大,甚至爆滿整個磁盤;而每套腳本
# 都重複寫一個日志滾動邏輯,顯然是件無聊的事,
# 甚至一些人懶得做處理,日子一久,就會發現一個超大的
# 日志檔案,本腳本希望可以幫助解決這個問題,讓大家無
# 後顧之憂。
# 使用方法:
# 1) 把腳本複制到日志檔案所在目錄,
# 然後以nohup ./log_rotater.sh > /dev/null & 等方式啟動腳本即可
# 2) 除了上面的方法,也可以将log_rotater.sh任何目錄下,
# 但這個時候,應當将backup_dir的值修改為日志檔案所在目錄
# sudo dpkg-reconfigure dash
# 新版本Ubuntu預設使用dash作為shell,
# 這個shell功能較弱,不支援數組等,但速度快,
# 可采取如下辦法檢測是何種shell:
# ls -l `which sh`
# 可根據需要修改以下參數
backup_count=10 # 日志滾動的個數
backup_size=$((1024 * 1024 * 200)) # 單個日志檔案大小
backup_interval=60 # 檢測的間隔時間,機關為秒
# 如果dirs_list指定的檔案存在,則從dirs_list中讀取目錄,
# 否則僅處理backup_dir指定的單個目錄
# 往dirs_list指定檔案增減目錄時,不需要重新開機log_rotater.sh
backup_dir=. # 日志檔案所在目錄
dirs_list=./dirs.list # 存儲目錄清單的檔案,要求一行一個目錄
# 處理單個目錄下的日志滾動
scan_single_dir()
{
dir=$1
cd $dir
if test $? -ne 0; then
return
fi
# 用到了awk給外部變量指派的特性
eval $(ls -l --time-style=long-iso *.log 2>/dev/null|awk '{ printf("filesize=%s\nfiledate=%s\nfilename=%s\n", $5,$6,$8); }')
if test -z $filename; then
if test $filesize -gt $backup_size; then
file_index=$(($backup_count - 1))
while test $file_index -gt 1; do
new_filename="${filename}.$file_index"
old_filename="${filename}.$(($file_index - 1))"
if test -f "$old_filename"; then
mv "$old_filename" "$new_filename"
file_index=$(($file_index - 1))
done
# 這裡需要使用truncate,而不能使用mv,
# 因為需要保持檔案的inode不變
cp "$filename" "${filename}.1"
truncate -s 1024 "$filename"
cd -
sleep 1
}
# 循環檢測
while true; do
if test ! -f $dirs_list; then
scan_single_dir $backup_dir
else
while read dirpath
do
scan_single_dir $dirpath
sleep $backup_interval