pid文件是logrotate重载服务日志的寻址依据,用于postrotate中通过sighup通知正确进程;需确保其存在、可读、指向存活进程,并与logrotate配置协同,避免日志丢失。

PID文件和logrotate配合使用,核心在于让logrotate在重载服务前准确找到进程ID,避免因服务未重启导致新日志仍写入旧文件。关键不是“用PID文件驱动logrotate”,而是让logrotate的postrotate脚本能通过PID文件向正确进程发送信号(通常是SIGHUP)。
理解PID文件的真实作用
PID文件本身不参与日志切割过程,它只是logrotate执行重载操作时的“寻址依据”:
- logrotate按配置轮转日志后,会执行
postrotate段里的命令 - 该段通常用
kill -HUP `cat /path/to/pidfile`通知服务重新打开日志文件 - 如果PID文件不存在、路径错误或权限不足,
postrotate会失败,服务继续往已重命名的旧日志写入,造成日志丢失 - 服务自身必须支持SIGHUP重载日志(如Nginx、Rsyslog默认支持;自研程序需自行实现)
编写可靠Shell脚本的关键步骤
不建议把logrotate逻辑全写进Shell脚本——logrotate本身已是成熟工具。应聚焦于:校验PID、安全重载、异常反馈。示例脚本(保存为/usr/local/bin/rotate-with-pid.sh):
-
检查PID文件存在且可读:
if [[ ! -r "/var/run/myapp.pid" ]]; then echo "PID file missing or unreadable"; exit 1; fi -
读取PID并验证进程是否存活:
pid=$(cat /var/run/myapp.pid); kill -0 $pid 2>/dev/null || { echo "Process $pid not running"; exit 1; } -
执行logrotate并捕获结果:
logrotate -s /var/lib/logrotate/status /etc/logrotate.d/myapp && status=$? || status=$? -
仅当logrotate成功才重载:
if [[ $status -eq 0 ]]; then kill -HUP $pid; fi
logrotate配置必须与脚本协同
在/etc/logrotate.d/myapp中明确指定PID路径,并禁用logrotate自带的reload指令(避免冲突):
/var/log/myapp/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
sharedscripts
postrotate
/usr/local/bin/rotate-with-pid.sh
endscript
}
注意:sharedscripts确保postrotate只执行一次(即使匹配多个日志文件);不要写reload或invoke,全部交给你的脚本控制。
常见陷阱与规避方法
PID文件路径不一致:服务启动时写的PID路径,必须和脚本里读的完全一致(含符号链接解析)。用readlink -f /var/run/myapp.pid确认真实路径。
权限问题:logrotate默认以root运行,但若服务以普通用户运行,PID文件可能属该用户。脚本中用sudo -u myuser kill -HUP $pid,或确保logrotate配置里加su root myuser。
PID文件延迟更新:某些服务在fork子进程后才写PID文件。可在脚本中加简单等待:for i in {1..5}; do [[ -s "/var/run/myapp.pid" ]] && break; sleep 0.5; done。











