Linux 服务无日志时的排查思路

3次阅读

服务无日志主因是默认走journald而非落盘,需查systemctl status、journalctl输出及service文件中StandardOutput/StandardError配置,必要时修改journald.conf或添加StandardOutput=append:/var/log/.log并reload。

Linux 服务无日志时的排查思路

服务启动了但 /var/log/ 下没日志文件

不是日志被删了,而是服务压根没配置写日志,或者日志被重定向到其他地方。很多 systemd 服务默认不落盘,只走 journald

  • 先查 systemctl status ,看最后一行有没有类似 journalctl -u 的提示
  • 运行 journalctl -u --since "1 hour ago" 看实时日志输出,确认服务是否真在跑、有没有报错
  • 检查服务单元文件:systemctl cat ,重点看 StandardOutputStandardError 字段——如果设成 journalNULL,就不会生成传统日志文件
  • 若想强制落盘,需在 service 文件里加 StandardOutput=append:/var/log/.log 并 reload:先 systemctl daemon-reload,再 systemctl restart

journalctl 查不到最近的日志

常见于系统重启后日志被轮转或限制了保留策略,不是命令用错了。

  • 默认 journald 只存内存+有限磁盘空间(通常 10% 或 4G),老日志会被自动清理。查当前配额:journalctl --disk-usage
  • 看保留策略:cat /etc/systemd/journald.conf | grep -E "^(Storage|SystemMaxUse|SystemMaxFileSize)";若 Storage=volatile,那所有日志都在 /run/log/journal/,重启即丢
  • 临时扩大空间:改 SystemMaxUse=500M 后执行 systemctl kill --signal=SIGUSR1 --kill-who=main systemd-journald 触发重载(不用 restart)
  • 注意:--since 时间格式要严格,"2024-05-20 14:30:00""2 hours ago" 更可靠,后者依赖系统时钟精度

服务进程在跑,但 journalctl 和文件日志都空

大概率是进程自己接管了 stdout/stderr,又没做任何输出,或者输出被重定向到某个没权限写的路径。

  • ps auxf | grep 找主进程 PID,再查它的文件描述符:ls -l /proc//fd/{1,2} —— 如果指向 /dev/null 或一个不存在的路径,就解释得通
  • 有些程序(如 Node.jspm2、Go 的二进制)默认静默,需显式加 --log 或设置环境变量如 LOG_LEVEL=debug
  • 检查服务是否以非 root 用户运行,而日志路径(比如 /var/log/myapp/)属主是 root 且无写权限 —— journalctl 不报权限错,但写文件会静默失败
  • 抓一把实时输出:strace -p -e write -s 200 2>&1 | grep -E "(write|"[^"]{5,}")",看它到底往哪写、写了啥

想让日志同时进 journald 和文件,但内容不一致

不是同步问题,是输出流被复制时发生了缓冲或截断 —— 尤其是短生命周期进程或带颜色输出的命令。

  • 避免用 tee 简单分流,它无法处理行缓冲和全缓冲混用的情况。正确做法是在服务配置中分别指定:StandardOutput=journal + StandardError=journal,再用 systemd-cat 做桥接(见下条)
  • 若必须落地文件,用 ExecStartPre=-/bin/mkdir -p /var/log/ 确保路径存在,再用 ExecStart=/usr/bin/stdbuf -oL -eL /path/to/binary 2>&1 | /usr/bin/systemd-cat -t
  • stdbuf -oL -eL 强制行缓冲,防止日志卡在缓冲区不吐;systemd-cat 保证每行都进 journal,且能被 journalctl -t 过滤
  • 注意:systemd-cat 不会自动创建日志文件,它只负责把标准输入转发给 journald —— 落盘还得靠 systemd-journald 自身的持久化配置

事情说清了就结束。真正卡住人的,往往不是“怎么查”,而是默认行为和权限细节——比如 Storage=auto 在某些发行版里实际等价于 volatile,或者 StandardOutput=journal 时连 printf 都可能因缓冲不刷新而消失。

text=ZqhQzanResources