db.runCommand({logRotate: 1})仅手动触发单次日志切换,不删除/压缩旧文件、无定时/按量策略、无法覆盖mongos/shard/config server等多节点,故不能防磁盘写满;必须为每个节点日志路径单独配置logrotate,配合logRotate: reopen与SIGUSR1信号实现自动轮转清理。

分片集群不能只靠 db.runCommand({logRotate: 1}) 实现自动轮转,它只是手动触发一次切换,不解决磁盘写满问题。真正防写满,得靠系统级日志轮转工具(如 logrotate)配合 MongoDB 的 reopen 行为,否则旧日志不清理、新日志不停写,磁盘迟早撑爆。
为什么分片集群的 logRotate 命令不能自动防写满
在 mongos 或任意 shard 节点上执行 db.runCommand({logRotate: 1}),只会让该进程立刻关闭当前日志、新建一个空 systemLog.path 文件——但:
- 它不删除、不压缩、不归档旧日志文件,原文件仍占磁盘空间
- 它不设置触发条件(比如“超 500MB 就轮”或“每天轮”),无法定时/按量自动执行
- 分片集群有多个独立进程(
mongos、每个shard的mongod、config server),必须对每个日志路径单独配置,不能靠一条命令覆盖全部
必须用 logrotate 配置每个节点的日志路径
每个 MongoDB 进程的日志路径是独立的,例如:
-
/var/log/mongodb/mongos.log(对应mongos) -
/var/log/mongodb/shard1.log(对应第一个shard) -
/var/log/mongodb/configsvr.log(对应 config server)
你得为每个路径写一份 logrotate 配置。以 shard1 为例(放在 /etc/logrotate.d/mongodb-shard1):
/var/log/mongodb/shard1.log {
size 500M
rotate 10
compress
missingok
notifempty
create 640 mongodb mongodb
postrotate
if [ -f /var/run/mongodb/shard1.pid ]; then
kill -SIGUSR1 $(cat /var/run/mongodb/shard1.pid)
fi
endscript
}
关键点:
-
size 500M:比logSizeMax更可靠,不受 MongoDB 进程内部计数误差影响 -
rotate 10:保留 10 个历史文件,避免无限堆积 -
postrotate中发SIGUSR1:通知 MongoDB 重新打开日志(前提是启动时用了--logappend --logRotate reopen或配置了logRotate: reopen) - 不要用
copytruncate:它会截断正在写的日志,可能丢最后几行;reopen+SIGUSR1才是安全组合
确保 MongoDB 启动参数或配置支持 reopen
如果 MongoDB 没启用 reopen 行为,SIGUSR1 信号会被忽略,logrotate 切完后新日志仍写进旧文件(导致日志分裂、内容错乱)。检查方式:
- 查进程启动命令:
ps aux | grep mongod | grep -o "logRotate.*reopen",应有输出 - 查配置文件(如
/etc/mongod.conf)中是否有:systemLog: logRotate: reopen logAppend: true
- 没配的话,必须加,并重启对应进程(
mongos、mongod等各自独立重启)
注意:logRotate: rename(默认值)不响应 SIGUSR1,只能靠 db.runCommand 手动切,无法与 logrotate 协同。
磁盘写满前最易被忽略的三个点
分片集群日志防写满,真正的风险不在配置本身,而在多节点一致性缺失:
- 忘了给
mongos配置——它也有日志,且高并发下增长极快,常被漏掉 -
postrotate脚本里 PID 路径写错(比如用了/var/run/mongodb.pid,但实际是/var/run/mongodb/mongos.pid),导致SIGUSR1发送失败,轮转后日志仍在写旧文件 - 各节点日志路径权限不对:
create 640 mongodb mongodb中的用户/组名必须和对应进程实际运行身份一致(mongos常用mongos用户,不是mongodb)
验证是否生效,别只看文件数量,要确认:ls -lt /var/log/mongodb/ 看最新日志是否时间戳最新、且大小从 0 开始增长;再 tail -f 新日志,确认实时写入无中断。


















