logrotate 通过 postrotate 脚本触发邮件告警,必须在日志归档完成后执行 mail 命令,并确保本地 mta 已安装运行;需用绝对路径获取归档文件信息、拼接含大小及错误统计的邮件正文,避免 prerotate 中读取未关闭的日志。

logrotate 配置中如何触发邮件告警
logrotate 本身不直接发邮件,但支持 postrotate 脚本,在日志切割完成后执行任意命令。关键不是“怎么配 logrotate”,而是“在哪个阶段调用 mail 或 sendmail 才可靠”。
常见错误是把发送逻辑写在 prerotate —— 此时旧日志还没被重命名或压缩,可能正在被进程写入,cat 或 tail 会读到不完整内容,甚至因文件被占用而失败。
- 必须放在
postrotate/endscript块内 - 确保目标日志已归档(如
/var/log/nginx/access.log.1)且不再被写入 - 检查
sharedscripts是否启用:多个日志文件共用同一组postrotate时需开启,否则每个文件都会单独触发一次
用 mail 命令发邮件前要确认什么
mail 命令看似简单,但实际运行常失败,根本原因不是配置错,而是本地 MTA(如 sendmail、postfix、msmtp)根本没装或没跑起来。
运行 echo "test" | mail -s "test" your@domain.com 报 Cannot open mail transfer agent 就是这个原因。
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
- 先执行
which sendmail或systemctl status postfix确认 MTA 存在且 active - 若只是告警用途,推荐轻量方案:
msmtp+ 外部 SMTP(如 Gmail、企业邮箱),避免部署完整邮件服务器 -
mail的-r参数指定发件人(部分 SMTP 服务强制要求),否则可能被拒收
如何让邮件内容包含切割详情和日志摘要
纯通知“已切割”意义不大,真正有用的是:切了哪个文件、大小多少、最近几行错误是否突增。这些信息得在 postrotate 里拼出来。
注意:$1 在 postrotate 中不可用(logrotate 不传参),必须用绝对路径或通配匹配归档文件。
- 用
ls -lh /var/log/app/*.log.[0-9]* 2>/dev/null | tail -n 3查最近归档 - 用
zgrep -c "ERROR\|500" /var/log/app/app.log.1.gz 2>/dev/null统计错误行数(支持 gzip) - 邮件正文建议用
printf拼接,避免echo对转义符处理不一致 - 别在脚本里硬编码邮箱,改用环境变量或独立配置文件,方便多环境复用
为什么日志切割后邮件总延迟或丢失
最隐蔽的问题是:logrotate 默认以 cron 每天执行一次(/etc/cron.daily/logrotate),但如果你手动运行 logrotate -f /etc/logrotate.d/myapp 测试,postrotate 里的 mail 可能因权限问题失败——因为 cron 是 root 运行,而手动执行时当前用户可能没权限读取归档日志或调用 sendmail。
- 测试时统一用
sudo -u root logrotate -f /etc/logrotate.d/myapp - 在
postrotate脚本开头加set -x和日志重定向(如>/var/log/logrotate-mail.log 2>&1)排查静默失败 - 如果用 systemd timer 替代 cron,注意
RuntimeMaxSec是否限制了脚本执行时长,大日志压缩+邮件发送可能超时
归档路径权限、MTA 队列积压、防火墙拦截 SMTP 端口(25/587)——这些点任何一个卡住,邮件就发不出,但 logrotate 自身仍返回成功,很难察觉。










