crontab触发日志切割需用绝对路径、设可执行权限、脚本内用绝对路径、正确发送信号;logrotate可通过-f参数配合crontab定时强制轮转;常见失败原因是未通知服务重开日志或信号发错对象。

crontab 怎么触发日志切割脚本
直接用 crontab -e 添加一行定时命令即可,关键是时间点和执行路径要写对。常见错误是脚本里用了相对路径或没指定环境变量,导致 cron 执行时找不到 LOG_FILE 或权限失败。
示例:每天凌晨 2:05 切割 /var/log/myapp.log
5 2 * * * /bin/bash /opt/scripts/rotate_myapp_log.sh
- 必须写全路径:
/bin/bash而不是bash,避免 cron 环境中 PATH 不一致 - 脚本本身要有可执行权限:
chmod +x /opt/scripts/rotate_myapp_log.sh - 脚本内所有路径(如
LOG_FILE、LOG_DIR)必须用绝对路径,不能依赖当前工作目录 - 如果脚本里调用了
kill -USR1,需确保 cron 运行用户有对应进程的信号发送权限(通常 root 更稳妥)
logrotate 怎么通过 crontab 触发
logrotate 本身不常驻,它靠系统级 cron(如 /etc/cron.daily/logrotate)驱动,但你可以手动干预或自定义调度。直接在用户 crontab 里调用 logrotate 是可行的,但要注意状态文件和并发问题。
例如,每小时强制轮转一次 Nginx 日志:
0 * * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx
-
-f参数强制执行,绕过默认的「一天一次」限制,适合高流量场景 - 配置文件中必须含
sharedscripts和postrotate,否则kill -USR1可能只执行一次或漏掉多个 worker 进程 - 避免多个 cron 同时调用同一配置:
logrotate默认用/var/lib/logrotate.status记录时间戳,但加-f会跳过该检查,所以得人工控制频率 - 若用非 root 用户运行,需确认其对日志文件、pid 文件、
/var/lib/logrotate.status有读写权限
为什么 cron 执行脚本后日志没切、磁盘空间也没释放
最常见原因是服务仍在往旧 inode 写日志,而你只重命名了文件名。Linux 进程靠 inode 不靠路径打开文件,mv 不影响写入,但新日志不会自动创建 —— 除非你显式通知服务重开日志或清空原文件。
- 没发信号:Nginx 需
kill -USR1,rsyslog 需kill -HUP,MySQL 一般不支持,只能用copytruncate - 信号发错对象:
cat /var/run/nginx.pid返回空?说明 pid 文件不存在或路径不对,脚本里得加判断 - 用了
rm或echo > xxx.log:前者删不掉占用中的文件(df显示空间未释放),后者会清空但破坏原子性,可能截断正在写的行 - 脚本里没检查
[ -s "$LOG_FILE" ]:空日志也执行mv,会导致下次运行时原文件缺失,脚本静默失败
按访问量或内存触发时,cron 频率怎么设才合理
不能无脑高频轮询。太密(如每分钟)会加重系统负担;太疏(如每小时)可能错过阈值窗口。核心是匹配监控粒度与业务节奏。
- 按行数切(模拟访问量):建议每 5 分钟跑一次脚本,配合
wc -l增量统计(记录上一次行数到临时文件),避免每次全量扫描大日志 - 按内存切:每 2–5 分钟查一次
free,阈值设 85% 比 95% 更安全,留出缓冲时间 - 注意
date +%Y%m%d_%H%M%S在高频场景下可能重复:同一秒内多次执行,会导致mv覆盖归档文件,应改用date +%Y%m%d_%H%M%S%3N(纳秒)或加随机后缀 - 所有条件型切割(大小/内存/行数)都应在脚本开头加锁,比如
if [ -f /tmp/rotate.lock ]; then exit; else touch /tmp/rotate.lock; trap 'rm -f /tmp/rotate.lock' EXIT,防止 cron 任务堆积并发冲突
实际中最容易被忽略的是信号发送后的等待逻辑 —— kill -USR1 返回成功不代表 Nginx 已完成重开日志,如果紧接着就 touch 新文件并 chown,可能因权限滞后导致 worker 进程写入失败。真要稳,得加简单校验,比如轮询 stat -c '%y' /var/log/nginx/access.log 看修改时间是否更新。











