抬头仰望星空,是否能发现自己的渺小。

伪斜杠青年

人们总是混淆了欲望和理想

Nginx 日志定时切割脚本

因为之前装了 fail2ban,对日志进行了一个统一管理,但是 nginx 本身不具备日志切割的功能,于是就导致了日志日积月累的庞大,面对一天十几万的 ssh 等各种乱七八糟的攻击请求,产生的日志不计其数,有必要进行每日切割。

解决办法:脚本 + 定时任务

原理:将日志以日期进行备份,再清除日志文件内容,达到类似切割的效果。

对于仅有一份日志的情况下脚本这样写:

#!/bin/bash
log_path=/usr/local/nginx/logs/access.log
save_path=/usr/local/nginx/logs/bak/access_$(date +%Y%m%d -d 'yesterday').log
cp $log_path $save_path && echo > $log_path

但我的情况以及很多人的情况肯定不会是只有一份日志,那么就需要用循环来解决了。

logcut.sh 内容如下(遍历文件 取文件名 按文件名创建文件夹 再清空日志):

#!/bin/bash
base_path=/path/to/nginx_log
backup_path=/path/to/log_backup
for log_path in $base_path/*; do
    log_name=$(basename $log_path .log)
    dstDir=$backup_path/$log_name
    if [ ! -d dstDir ]; then
        mkdir -p $dstDir
    fi
    save_path=$dstDir/log_$(date +%Y%m%d -d 'yesterday').log
    cp $log_path $save_path && echo >$log_path
done

创建定时任务:

$crontab -e

输入内容:

0 0  * * * /path/to/logcut.sh #每天的00:00执行日志切分

查看定时任务是否添加成功:

crontab -l

后续

经过多次迭代,最后找 GPT 优化了一个最终版:

#!/bin/bash

# 默认选择为备份
idx='backup'

# 处理用户输入
if [ -z "$1" ]; then
echo ""
echo " backup: backup log now."
echo " clean: clean backup log"
echo ""
read -p "Please input: " idx
else
idx="$1"
fi

# 配置路径
log_path="/path/to/nginx_log"
backup_dst="/path/to/log_backup"

backup_log() {
for log_file in "$log_path"/*.log; do
# 检查日志文件是否存在,避免处理不存在的文件
[ -e "$log_file" ] || continue

# 获取文件名(去除路径和扩展名)
log_name=$(basename "$log_file" .log)
save_dir="$backup_dst/$log_name"

# 创建保存目录(如果不存在)
[ ! -d "$save_dir" ] && mkdir -p "$save_dir"

# 生成备份文件名
save_dst="$save_dir/log_$(date +%Y%m%d -d 'yesterday').log"

# 备份日志并清空原始日志
cp "$log_file" "$save_dst" && : > "$log_file"

# 更新备份目录的修改时间
touch "$save_dir"
done

# 更新备份目录本身的修改时间
touch "$backup_dst"
}

clean_log() {
find "$backup_dst" -type f -mtime +60 -exec rm -rfv {} \;
}

# 根据用户输入执行操作
case "$idx" in
backup)
echo "Backup log start."
backup_log
;;
clean)
echo "Clean log start."
clean_log
;;
*)
echo "Invalid, exit!"
;;
esac

以上。

参考:

Nginx access.log文件太大,自动释放清理


本站由以下主机服务商提供服务支持:

0条评论

发表评论