修改配置并利用日志排错

服务上线后,管理员最核心的日常工作,就是改配置和看日志。

例如,图书馆要求把服务端口从 8080 改成 8081,或者把公告目录换成另一个发布目录。改完之后,新配置什么时候生效?如果配置文件里少写了引号、路径不存在,导致服务启动失败,又该怎么从日志里定位问题?

这一节我们主动制造两类常见故障,并演练如何用日志排查。

改配置前先备份

修改任何配置文件之前,先备份,养成习惯:

crow@opsbox:~/work$ sudo cp /etc/bulletin/server.env /etc/bulletin/server.env.bak
crow@opsbox:~/work$ sudo nano /etc/bulletin/server.env

在打开的编辑器里,把:

PORT=8080

改成:

PORT=8081

保存并退出。

修改监听端口并重载服务

配置文件改了,并不意味着服务马上生效。正在运行的 bulletin 进程仍在使用旧配置,直接访问 8081 会连接失败。要让新配置生效,需要重启服务:

crow@opsbox:~/work$ sudo systemctl restart bulletin
crow@opsbox:~/work$ ss -ltn 'sport = :8081'
crow@opsbox:~/work$ curl -sS http://127.0.0.1:8081/hours.txt
图书馆开放时间:09:00-18:00

如果 ss 命令没有输出,通常说明端口没有监听,可以检查配置文件是否写对,或查看日志定位原因。

重要

什么时候执行 daemon-reload?

  • 只修改外部环境文件,例如 /etc/bulletin/server.env:直接 sudo systemctl restart 服务名 即可。
  • 修改了 .service 单元文件本身,例如 /etc/systemd/system/bulletin.service:先执行 sudo systemctl daemon-reload,让 systemd 重新读取单元定义,再执行 restart。

使用 journalctl 查看服务日志

由 systemd 管理的服务,日志一般会被统一收集到 journald 中。查看 bulletin 服务最近日志:

crow@opsbox:~/work$ sudo journalctl -u bulletin -n 20 --no-pager

常用选项:

  • -u bulletin:只看 bulletin 服务的日志。
  • -n 20:只看最近 20 行。
  • --no-pager:不进入分页器,直接输出结果。
  • -f:持续跟踪新日志,类似 tail -f;按 Ctrl+C 退出。

排错时建议从“最近一次启动前后”的日志看起,再根据报错时间向前扩展。

排错演练 A:服务在运行,但资源返回 404

有时服务状态看起来正常,但用户请求文件失败。我们故意把发布目录改成一个不存在的目录,看看日志会如何反映问题。

制造问题

crow@opsbox:~/work$ sudo nano /etc/bulletin/server.env
crow@opsbox:~/work$ sudo systemctl restart bulletin
crow@opsbox:~/work$ systemctl is-active bulletin
active
crow@opsbox:~/work$ curl -I http://127.0.0.1:8081/hours.txt
HTTP/1.0 404 File not found

注意:这里 systemctl is-active 返回的是 active,但请求文件仍然失败。

为什么服务状态和 HTTP 状态可能不一致

systemctl is-active 只说明 bulletin 对应的进程还在运行,通常也说明端口已经被监听。HTTP 404 是应用层状态码,表示服务收到了请求,但找不到请求对应的资源。

因此,服务“活着”不代表它一定能正常提供文件。文件路径配置错误、目录不存在、文件被移动,都可能出现“服务状态 active,但页面资源 404”的情况。

用日志确认原因

先看最近日志:

crow@opsbox:~/work$ sudo journalctl -u bulletin -n 5 --no-pager

如果日志中提示找不到目录或文件,再检查目录是否存在:

crow@opsbox:~/work$ ls -ld /srv/bulletin-missing
ls: cannot access '/srv/bulletin-missing': No such file or directory

这说明问题不是端口冲突,也不是服务进程崩溃,而是配置文件里的 ROOT 指向了一个不存在的路径。

恢复配置

把刚才备份的文件复制回去,并重启服务:

crow@opsbox:~/work$ sudo cp /etc/bulletin/server.env.bak /etc/bulletin/server.env
crow@opsbox:~/work$ sudo systemctl restart bulletin
crow@opsbox:~/work$ curl -sS http://127.0.0.1:8080/hours.txt
图书馆开放时间:09:00-18:00

这里访问 8080,是因为备份文件里保存的还是旧配置。若需要继续使用 8081,应在恢复后再次修改 PORT=8081 并重启服务。

排错演练 B:配置写错导致服务启动崩溃

第二类故障更常见:配置字段类型错误,导致程序启动时直接退出。

制造问题

把 server.env 中的端口号改成非法值:

crow@opsbox:~/work$ sudo nano /etc/bulletin/server.env
crow@opsbox:~/work$ sudo systemctl restart bulletin
crow@opsbox:~/work$ sudo journalctl -u bulletin -n 20 --no-pager

在日志里可以看到类似这样的错误:

python3[467]: server.py: error: argument port: invalid int value: 'eight'
bulletin.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
bulletin.service: Failed with result 'exit-code'.

读懂这几行日志

  • argument port: invalid int value: 'eight':程序需要整数端口号,但配置里写成了英文字符串 eight。
  • Main process exited, ... status=2/INVALIDARGUMENT:主进程因为参数无效而退出。
  • Failed with result 'exit-code':systemd 认为服务启动失败,而不是“还在运行但请求报错”。

如果单元文件配置了 Restart=on-failure,systemd 会尝试反复拉起进程。多次失败后,服务状态会变成 failed。

修复步骤

  1. 编辑配置文件,把非法值改回正确值,例如 PORT=8081。
  2. 保存文件。
  3. 如果服务已处于 failed 状态,可以先重置失败记录:sudo systemctl reset-failed bulletin
  4. 启动服务:sudo systemctl start bulletin
  5. 验证服务状态和端口:systemctl is-active bulletin、ss -ltn 'sport = :8081'
  6. 使用 curl 检查页面资源:curl -sS http://127.0.0.1:8081/hours.txt

快速检查:日志能直接支持什么判断

假设你看到以下现象:

crow@opsbox:~/work$ systemctl is-active bulletin
active
crow@opsbox:~/work$ curl -I http://127.0.0.1:8081/hours.txt
HTTP/1.0 404 File not found

日志记录了什么

练习

仅凭上面这两行输出,下面哪项判断最可靠?

A. 服务进程仍在运行,但应用层找不到请求对应的资源。 B. 文件一定是被人删除了。 C. 一定是权限设置错误导致的。 D. 服务已经没有监听端口。

提交选项字母。

提交答案

题解 Hint