背景
把系统邮件通道修通(新 SMTPS 服务严格投递 + 发件人/收件人改写)后,一批原本就存在、只是以前没人收到告警的系统运维问题陆续”显形”——因为以前这些失败邮件发不出去或没人看,现在能正常送达了。本文汇总这几个独立但同源的问题。
问题一:logrotate 配置文件权限过宽被忽略
现象:error: Ignoring rails because of bad file mode - must be 0644 or 0444
根因:某个 logrotate 配置文件权限是 755(带可执行位)。logrotate 出于安全考虑会拒绝加载权限过宽的配置文件,直接忽略。导致对应的应用日志长期没有被轮转,文件无限增长(出现过 6GB 的单个日志)。
修复:chmod 644。修好后 logrotate 恢复加载,日志恢复正常轮转。
问题二:日志文件轮转时 Permission denied(两个 logrotate 打架)
现象:error: stat of .../应用日志 failed: Permission denied
根因:系统上有两个 logrotate 入口都在处理同一份应用日志配置:
- 系统自带的
cron.daily/logrotate - root crontab 里一条定时 logrotate
应用日志配置里有 su <服务账号> 指令(降权操作)。cron.daily 入口在其执行上下文 + 服务账号家目录权限(750/700)+ SELinux 组合下,降权后无法穿越家目录去访问日志 → Permission denied。而 root crontab 那条直接以 root 跑,能成功轮转。所以日志实际被成功轮转了,但 cron.daily 入口每天失败并发告警邮件。
修复(方案 C:职责分离):
前提:原 root crontab 那条 logrotate 处理的是整个
logrotate.conf(会包含/etc/logrotate.d/下所有配置,含应用日志)。所以不能简单删掉某个入口了事——需要把应用日志单独拆出来专管。
- 把应用日志的 logrotate 配置从
/etc/logrotate.d/移到应用自己的目录(这样 cron.daily 和原 crontab 的logrotate.conf都不再处理它) - root crontab 新增一条专门处理这个独立配置文件的 logrotate(以 root 身份直接跑,不带
su降权问题,能成功轮转) - 结果:cron.daily 不再报错,应用日志轮转由新增的 root crontab 条目独立完成;真实强制轮转验证成功(退出码 0、生成归档)
问题三:无效的 mysql 清理 cron 任务
现象:Cron ... mysql -e "PURGE BINARY LOGS ..." ERROR 1045 Access denied for user 'root'@'localhost'
根因:root crontab 有一条定时任务,用裸 mysql 命令(不带主机/账号/密码)清理 binlog。但应用的数据库在远程托管 MySQL 服务器上,不在本机。裸命令连的是本机 localhost,被拒绝认证。该任务从设计上就一直失败,且 binlog 清理本应由托管 MySQL 服务/DBA 负责,不该由应用主机做。
修复:注释禁用这条无效 cron,并加说明注释。(预发布环境非配置管理托管,可直接改;生产环境确认已无配置管理 agent 周期性覆盖后同样处理。)
问题四:puppet logrotate 配置引用不存在的用户
现象:error: puppet:4 unknown user 'puppet'
根因:/etc/logrotate.d/puppet 配置要求以 puppet 用户创建文件,但该主机已不再运行配置管理 agent,系统里没有 puppet 用户,每天 logrotate 运行时报错。
修复:删除该无意义的 logrotate 配置文件(主机已无相关服务)。
共同启示
这几个问题都不是邮件迁移引入的,而是长期潜伏的运维配置缺陷。邮件通道修通后,它们的失败告警终于能送达,起到了”体检”作用——把隐藏多年的问题一次性暴露并修复。这也是把告警邮件打通的额外收益。
通俗版复述
这是怎么回事?
把邮件通道彻底修好之后,突然收到一堆系统报错邮件。一开始以为是我们搞坏了,细查才发现:这些毛病早就存在,只是以前系统报错的邮件根本发不出去、没人看见,现在邮件通了,它们才一股脑冒出来——相当于邮件修通顺带做了次”全身体检”,查出几个陈年老毛病:
日志不清理:有个管”日志轮换”的配置文件权限设得太松,负责轮换的程序出于安全直接无视它,导致日志一直不清理、涨到 6GB。改一下权限就好。
两个程序抢着干同一件事:有两个定时程序都去轮换同一份日志,其中一个因为权限/身份问题每次都失败、天天报错,另一个其实已经默默干成了。解决办法是让它俩分工——把这份日志交给能干成的那个专管,另一个不再碰。
一个根本连不上的定时任务:有个定时任务想去清理数据库日志,但它连的是”本机数据库”,而真正的数据库在远程,所以从来就没成功过、天天报错。而且这活本该数据库那边自己管。直接把这个没用的任务停掉。
找一个不存在的用户:有个日志轮换配置要用”puppet”这个用户来干活,但这台机器早就没有这个用户了,天天报错。把这个没用的配置删掉。
一句话:邮件修通后顺手把几个藏了很久的系统小毛病也一并清理了。