Linux 服务日志缺失的定位方法

16次阅读

journalctl 查不到日志的首要原因是服务未由 systemd 管理;其次可能是日志输出被重定向、daemon 化、配置了 StandardOutput=null、日志存储模式为 volatile、磁盘配额满、文件权限或 SELinux 限制。

Linux 服务日志缺失的定位方法

journalctl 查不到服务日志,先确认服务是否由 systemd 管理

很多用户执行 journalctl -u nginxjournalctl -u myapp 返回空结果,第一反应是日志丢了,其实更可能是服务压根没用 systemd 启动。比如直接运行 ./server、用 nohup 启动,或通过容器(Docker/Podman)运行——这些场景下 journalctl 默认看不到日志。

验证方法很简单:

  • 运行 systemctl list-units --type=service | grep myapp,看服务名是否在列表中且状态为 loaded
  • 检查 /etc/systemd/system/myapp.service/usr/lib/systemd/system/myapp.service 是否存在
  • 若服务是手动启动的,ps aux | grep myapp 查看其父进程:如果 PPID 是 1 但不是 systemd(比如是 containerd 或 bash),那它就不受 journalctl 管控

systemd 服务启用了 StandardOutput=journal,但日志仍不出现

即使服务已注册为 systemd unit,日志也可能“不可见”,常见原因是日志输出未被正确捕获。默认情况下,systemd 只捕获写入 stdout/stderr 的内容,且要求进程不自行重定向、不 fork 成守护进程(daemonize)。

典型问题和修复方式:

  • 服务脚本里写了 nohup ./app & 或调用 daemon(),导致子进程脱离 systemd 控制 → 改用 Type=simple 并禁用 daemon 模式,或改用 Type=forking + 正确设置 PIDFile=
  • 应用内部把 stdout/stderr 重定向到文件(如 log4j2.xml 配置了 FileAppender)→ 日志根本没经过 systemd → 要么改配置输出到 console,要么保留文件日志并用 journalctl --directory /var/log/journal 配合外部轮转
  • StandardOutput=nullStandardError=none 被显式设置 → 检查 service 文件,删掉或改为 journal

journalctl 显示日志但时间范围不对或条目过少

默认 journalctl 只查当前 boot 的日志,而服务可能在上一次重启前就运行了,或者日志被自动清理了。

关键排查点:

  • --all--no-pager 排除分页 / 过滤干扰:journalctl -u myapp --all --no-pager | head -20
  • 查全部 boot 记录:journalctl --list-boots,再指定 boot:journalctl -u myapp -b -1(上一次启动)
  • 确认日志存储模式:cat /etc/systemd/journald.conf | grep Storage。若为 Storage=volatile,则日志只存内存,重启即丢 → 改为 persistent 并确保 /var/log/journal/ 目录存在且可写
  • 检查磁盘配额:journalctl --disk-usage,若达到 SystemMaxUse= 限制(默认通常 10% 或 4G),旧日志会被自动删除

服务日志写到了文件,但文件为空或权限拒绝

有些服务(如 Nginx、MySQL)默认不走 systemd 日志,而是写入独立文件(如 /var/log/nginx/error.log)。这时缺失日志往往不是 journal 的问题,而是路径、权限或 SELinux 卡住了。

快速定位步骤:

  • 查服务配置里日志路径:Nginx 看 error_log 指令,Redis 看 logfile 配置项
  • 确认目录存在且服务用户有写权限:ls -ld /var/log/myapp/stat -c "%U %G" /var/log/myapp/
  • 若用非 root 用户运行服务(如 User=www-data),但 /var/log/myapp/ 属于 root:root 且无 group 写权限 → 日志写入失败,且常静默失败(不报错)
  • SELinux 启用时,即使权限看着对,也可能被阻止:ausearch -m avc -ts recent | grep myapp,或临时设为 permissive 模式验证

真正麻烦的永远不是“日志在哪”,而是“日志本该写,却因权限、路径、daemon 化或 systemd 配置偏差,压根没产生”。每次怀疑日志缺失,优先用 strace -p $(pgrep myapp) -e write 看进程是否真的在调用 write() 到 stdout/stderr 或指定文件描述符。

text=ZqhQzanResources