通过规范命名和脚本解析实现按PID切割日志,配置logrotate使用通配符匹配含PID的日志文件,结合copytruncate与postrotate脚本提取PID并发送USR1信号,确保多实例日志分离且写入不中断。

Linux系统中,日志文件会随着时间不断增长,影响磁盘空间和检索效率。logrotate 是 Linux 下常用的日志管理工具,可以自动对日志进行轮转、压缩、删除等操作。通常 logrotate 按时间或大小切割日志,但有时需要按进程 ID(PID)区分不同实例的日志,比如多个相同服务并行运行时。下面介绍如何配置 logrotate 实现按进程 ID 切割日志的实用方法。
理解 logrotate 基本机制
logrotate 通过配置文件定义日志处理规则,一般位于 /etc/logrotate.conf 和 /etc/logrotate.d/ 目录下。核心功能包括:
- 按天、周、月或日志大小触发轮转
- 保留指定数量的旧日志
- 轮转后执行自定义脚本(如重启服务或发送信号)
- 支持 compress、copytruncate、missingok 等选项
但 logrotate 本身不直接支持“按 PID 切割”,需要结合命名策略与脚本控制实现。
按进程 ID 切割日志的场景与思路
某些服务可能以多实例方式运行,每个实例使用独立的日志文件,例如:
- 多个 Python 后台任务进程
- 测试环境中并行启动的多个 daemon 实例
- 容器化前的手动进程隔离部署
此时希望每个进程的日志单独切割,避免混淆。实现思路如下:
- 每个进程启动时生成带 PID 的日志文件,如 /var/log/myapp/myapp.pid1234.log
- 为这类日志编写动态匹配的 logrotate 配置
- 在 postrotate 脚本中向对应 PID 发送信号,通知重新打开日志文件
具体配置步骤
假设你有多个 myapp 进程,日志路径为 /var/log/myapp/myapp.pid*.log,每个文件名包含其进程 ID。
1. 创建专用配置文件新建 /etc/logrotate.d/myapp-by-pid:
/var/log/myapp/myapp.pid*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
copytruncate
sharedscripts
postrotate
for logfile in "$@"; do
pid=$(echo "$logfile" | grep -o 'pid[0-9]*' | cut -d'p' -f3)
if [ -n "$pid" ] && kill -0 $pid 2>/dev/null; then
kill -USR1 $pid
logger "Sent USR1 to PID $pid for log reopen"
fi
done
endscript
}
2. 配置说明
- /var/log/myapp/myapp.pid*.log:通配符匹配所有含 PID 的日志
- copytruncate:适用于无法重开日志的程序,先复制再清空原文件
- sharedscripts:所有匹配文件只执行一次 postrotate 脚本
- postrotate...endscript:提取文件名中的 PID,并向该进程发送 USR1 信号(需程序支持)
- 应用程序需能响应 SIGUSR1 并重新打开日志文件
- 确保日志文件命名规范统一,便于提取 PID
- 若不支持信号,可改用 copytruncate 避免写入中断
验证与调试
测试配置是否正确:
- 手动运行:logrotate -d /etc/logrotate.d/myapp-by-pid(调试模式)
- 实际执行:logrotate -f /etc/logrotate.d/myapp-by-pid
- 查看系统日志:tail /var/log/messages 或 journalctl -u logrotate
确认旧日志被压缩,新文件创建,且进程继续写入无报错。
基本上就这些。虽然 logrotate 不原生支持按 PID 切割,但通过规范命名 + 通配匹配 + 脚本解析,完全可以实现精细化管理。关键是应用层配合信号处理,或使用 copytruncate 保证写入连续性。










