当MongoDB进程返回故障码2120时,通常意味着服务在尝试轮换系统日志文件时没有成功。此时mongod可能不会退出,但日志文件会停留在旧文件句柄上,新的运行日志要么丢失,要么继续写入已经被重命名的文件,给后续追踪错误和审计带来麻烦。故障码2120并不是MongoDB核心引擎故障,它更多指向日志输出链路中的文件系统、权限、外部调度脚本或信号交互问题。先理解这个错误码的产生位置,能帮助更快缩小排查范围。

一、理解MongoDB的日志轮换逻辑
MongoDB的日志输出由 systemLog 配置段控制。最常用的方式是写入文件,并设置 logAppend: true 让进程持续追加内容。当需要轮换日志时,MongoDB不会自动完成文件重命名,它依赖两种触发方式。第一种是内部命令 db.adminCommand({ logRotate: 1 }),这种方式会让MongoDB关闭当前日志文件,然后根据配置重新打开一个新文件。第二种是外部信号 SIGUSR1,向mongod进程发送该信号后,进程会执行一次reopen操作,也就是关闭当前文件句柄并重新打开配置中指定的日志路径。
在Linux环境中,系统级的logrotate工具一般会先通过配置文件对日志文件做重命名、压缩等处理,再通过postrotate脚本向mongod发送SIGUSR1信号。这个协作过程要求mongod能够再次以原路径打开日志文件。如果重命名后的目录不可写、文件属主发生变化、或者进程没有收到信号,就会出现轮换失败。MongoDB将这类错误统一标记为2120,日志中常见记录为 Failed to rotate log file, code: 2120。
这里的关键点是,mongod收到SIGUSR1后不会自行创建已经不存在的新文件,除非日志目录权限允许它创建。因此,很多看似是MongoDB自身故障的问题,实际根源在logrotate的create指令、目录权限或系统安全策略。
二、故障码2120的常见触发点
排查时可以先从文件系统权限入手。mongod进程通常以专用用户运行,例如mongodb用户。如果日志目录被改成root所有,或者权限被收紧为 700,那么mongod就无法重新创建日志文件。尤其在使用logrotate的create参数时,如果创建的新文件属主仍然是root,而mongod没有写入权限,下一次轮换就会失败。
除权限外,磁盘空间和inode耗尽也是高频原因。日志文件虽然不大,但频繁轮换会产生大量小文件,如果分区中的inode被占满,即便磁盘空间足够,进程也无法创建新文件。此时手动执行日志轮换命令会直接返回2120错误。
另一个容易忽略的场景是SELinux或AppArmor。很多生产环境会启用强制访问控制,当mongod尝试在非默认路径写日志时,安全策略可能直接拦截文件创建或重新打开操作,而MongoDB日志中只会表现为2120。检查审计日志可以帮助确认是否属于这一类。
查看日志目录权限和磁盘状态的命令如下:
ls -ld /var/log/mongodb ls -l /var/log/mongodb/mongod.log df -h /var/log/mongodb df -i /var/log/mongodb
如果怀疑是SELinux导致,可以进一步查看审计日志:
sudo ausearch -m avc -ts recent | grep mongod sudo tail -n 50 /var/log/audit/audit.log | grep mongod
三、修复方案与正确的logrotate配置
首先需要保证MongoDB的日志配置项正确。以下是一个典型的 mongod.conf 日志配置片段:
systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log logRotate: reopen verbosity: 0
这里 logRotate: reopen 表示mongod在收到SIGUSR1信号后,会关闭当前文件句柄,并尝试重新打开 path 指定的日志文件。这个行为要求日志目录可写,否则就会出现2120错误。
logrotate配置需要与上述模式匹配。常见的错误是只重命名文件,却没有在postrotate中给mongod发送信号,导致进程继续写旧inode。推荐配置如下:
/var/log/mongodb/mongod.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
create 640 mongodb mongodb
sharedscripts
postrotate
/usr/bin/kill -SIGUSR1 $(cat /var/run/mongodb/mongod.pid) || true
endscript
}
在上面的配置中,create 640 mongodb mongodb 会在轮换后创建新文件,并指定正确的属主和权限。postrotate使用pid文件定位mongod进程,比直接使用 pidof mongod 更可靠,尤其是同一台机器上运行多个MongoDB实例时。
如果目录权限已经混乱,可以先手动修复:
sudo chown -R mongodb:mongodb /var/log/mongodb sudo chmod 750 /var/log/mongodb sudo restorecon -Rv /var/log/mongodb
执行完成后,再运行 logrotate -d 调试配置语法,确认没有明显错误。
四、验证修复效果与长期预防
修复配置后,建议先手动触发一次MongoDB内部日志轮换,确认返回结果正常。使用mongosh执行命令:
mongosh --eval "db.adminCommand({ logRotate: 1 })"
如果返回内容中包含 ok: 1,说明MongoDB已经能够正常执行轮换。此时可以观察日志目录,应该出现新的日志文件,并且旧文件按预期被重命名或压缩。若仍然返回2120,需要继续检查文件句柄是否被其他进程占用,可以用 lsof 查看:
sudo lsof -p $(pidof mongod) | grep mongod.log ls -li /var/log/mongodb/mongod.log
长期来看,建议将2120错误纳入监控告警。可以通过脚本定期扫描MongoDB日志中的 code: 2120 关键字,一旦出现就通知运维人员。同时避免在日志轮换中使用 copytruncate 模式,因为该模式会在写入频繁时造成日志内容截断,并且无法与SIGUSR1信号正确配合。
最后,根据实际日志写入量设置合理的轮换周期。日志量较大的实例可以每天轮换一次,并保留七到十四天;日志量较小的情况下,每周轮换也足够。稳定的轮换策略配合正确权限和信号处理,能从根源上避免MongoDB故障码2120反复出现。
MongoDB故障码2120日志轮换失败logrotate修改时间:2026-10-03 14:39:57