Systemd 服务启动故障排查实战指南
一、背景介绍
Systemd 是现代 Linux 发行版的标准初始化系统和服务管理器。在生产环境中,服务无法正常启动是运维人员经常遇到的问题。本文将系统性地介绍 systemd 服务启动故障的排查方法和实战案例。
二、Systemd 基础概念
2.1 核心组件
| 组件 |
说明 |
| systemd |
系统和服务管理器 |
| systemctl |
控制 systemd 的命令行工具 |
| journalctl |
查看 systemd 日志的工具 |
| .service 文件 |
服务单元配置文件 |
2.2 服务状态
1 2 3 4 5 6 7 8
| systemctl status <service-name>
systemctl is-enabled <service-name>
systemctl is-active <service-name>
|
三、常见故障类型与排查方法
3.1 服务启动失败
症状
1 2
| $ systemctl start myapp Job for myapp.service failed because the control process exited with error code.
|
排查步骤
步骤 1:查看详细状态
1
| systemctl status myapp.service -l --no-pager
|
步骤 2:查看服务日志
1 2 3 4 5
| journalctl -u myapp.service -n 50 --no-pager
journalctl -u myapp.service -b --no-pager
|
步骤 3:检查依赖服务
1 2 3 4 5
| systemctl list-dependencies myapp.service
systemctl status <dependency-service>
|
步骤 4:手动执行启动命令
1 2 3 4 5
| systemctl cat myapp.service
/usr/bin/myapp --config /etc/myapp/config.yaml
|
3.2 服务启动后立刻退出
常见原因
- 配置文件错误
1 2 3 4 5
| myapp --check-config
ls -la /etc/myapp/config.yaml
|
- 端口被占用
1 2 3 4
| ss -tlnp | grep <port> netstat -tlnp | grep <port> lsof -i :<port>
|
- 权限不足
1 2 3 4 5 6
| systemctl cat myapp.service | grep User
ls -la /var/log/myapp/ ls -la /var/lib/myapp/
|
- 资源限制
1 2 3 4 5 6 7
| systemctl show myapp.service | grep -E "Limit|Memory|CPU"
free -h df -h ulimit -a
|
3.3 服务超时启动
症状
1 2
| $ systemctl start myapp Job for myapp.service timed out.
|
排查方法
步骤 1:增加超时时间临时测试
1
| systemctl start myapp.service --timeout=300
|
步骤 2:修改服务超时配置
1 2 3 4 5 6
| systemctl edit myapp.service
[Service] TimeoutStartSec=300
|
步骤 3:检查启动阻塞原因
1 2 3 4 5
| systemd-analyze blame | head -20
systemd-analyze critical-chain myapp.service
|
3.4 循环重启故障
症状
1 2 3 4
| $ systemctl status myapp.service ● myapp.service - My Application Loaded: loaded (/etc/systemd/system/myapp.service; enabled) Active: activating (auto-restart)
|
排查方法
步骤 1:查看重启次数
1
| systemctl show myapp.service | grep -E "NRestarts|RestartSec"
|
步骤 2:临时禁用自动重启
1 2 3 4
| systemctl edit myapp.service
[Service] Restart=no
|
步骤 3:分析重启原因
1 2
| journalctl -u myapp.service --since "1 hour ago" | grep -E "Started|Stopped|Failed"
|
四、实战案例
案例 1:Nginx 服务启动失败
问题现象
1 2
| $ systemctl start nginx Job for nginx.service failed.
|
排查过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $ systemctl status nginx.service ● nginx.service - A high performance web server Loaded: loaded (/lib/systemd/system/nginx.service; enabled) Active: failed (Result: exit-code) Process: 12345 ExecStart=/usr/sbin/nginx (code=exited, status=1/FAILURE)
$ journalctl -u nginx.service -n 20 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
$ ss -tlnp | grep :80 LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("apache2",pid=5678,fd=4))
$ systemctl stop apache2 $ systemctl start nginx
|
案例 2:MySQL 服务启动超时
问题现象
1 2
| $ systemctl start mysql Job for mysql.service timed out.
|
排查过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| $ systemd-analyze critical-chain mysql.service mysql.service +1min 30s
$ journalctl -u mysql.service | grep "InnoDB" InnoDB: Starting crash recovery... InnoDB: This may take several minutes...
$ systemctl edit mysql.service [Service] TimeoutStartSec=600
innodb_fast_shutdown=0
$ systemctl daemon-reload $ systemctl start mysql
|
案例 3:自定义服务权限问题
问题现象
1 2
| $ systemctl status myapp Active: failed (Result: exit-code)
|
排查过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| $ systemctl cat myapp.service [Service] User=myapp Group=myapp ExecStart=/opt/myapp/bin/myapp WorkingDirectory=/opt/myapp
$ ls -la /opt/myapp/ drwxr-xr-x 3 root root 4096 Mar 18 10:00 . drwxr-xr-x 20 root root 4096 Mar 18 10:00 .. drwxr-xr-x 2 root root 4096 Mar 18 10:00 logs
$ chown -R myapp:myapp /opt/myapp $ chmod 755 /opt/myapp/bin/myapp
$ systemctl start myapp $ systemctl status myapp ● myapp.service - My Application Active: active (running)
|
五、高级排查技巧
5.1 使用 strace 追踪系统调用
1 2 3 4 5 6 7 8
| EXEC_START=$(systemctl cat myapp.service | grep ExecStart | cut -d= -f2)
strace -f -o /tmp/myapp.strace $EXEC_START
grep -E "EACCES|ENOENT|EPERM" /tmp/myapp.strace
|
5.2 使用 systemd 调试模式
1 2 3 4 5 6
| systemctl set-log-level debug
systemctl restart myapp.service journalctl -u myapp.service --priority=debug
|
5.3 服务依赖树分析
1 2 3 4 5
| systemd-analyze dot | dot -Tsvg > /tmp/systemd.svg
systemctl list-dependencies myapp.service --reverse
|
六、预防措施
6.1 服务配置最佳实践
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| [Unit] Description=My Application Service Documentation=https://docs.myapp.com After=network.target postgresql.service Wants=postgresql.service
[Service] Type=notify User=myapp Group=myapp WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/bin/myapp --config /etc/myapp/config.yaml ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure RestartSec=5 TimeoutStartSec=120 TimeoutStopSec=30
MemoryLimit=2G CPUQuota=80%
NoNewPrivileges=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/var/log/myapp /var/lib/myapp
[Install] WantedBy=multi-user.target
|
6.2 监控与告警
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| cat > /usr/local/bin/check-systemd-services.sh << 'EOF'
FAILED_SERVICES=$(systemctl --failed --no-legend | wc -l) if [ $FAILED_SERVICES -gt 0 ]; then echo "CRITICAL: $FAILED_SERVICES systemd services failed" systemctl --failed --no-legend exit 2 fi echo "OK: All systemd services healthy" exit 0 EOF
chmod +x /usr/local/bin/check-systemd-services.sh
|
七、常用命令速查
| 命令 |
说明 |
systemctl status <svc> |
查看服务状态 |
systemctl start/stop/restart <svc> |
启动/停止/重启服务 |
systemctl enable/disable <svc> |
启用/禁用开机自启 |
journalctl -u <svc> -f |
实时查看服务日志 |
systemctl cat <svc> |
查看服务配置文件 |
systemctl edit <svc> |
编辑服务覆盖配置 |
systemctl daemon-reload |
重新加载 systemd 配置 |
systemd-analyze blame |
分析启动时间 |
systemctl list-dependencies <svc> |
查看服务依赖 |
八、总结
Systemd 服务启动故障排查需要遵循系统性的方法:
- 先看状态:
systemctl status 获取基本信息
- 再看日志:
journalctl -u 查看详细错误
- 检查依赖:确认依赖服务正常
- 手动测试:排除 systemd 因素
- 分析资源:检查权限、端口、文件等资源
掌握这些方法,可以快速定位和解决绝大多数 systemd 服务启动问题。
文档版本: v1.0
最后更新: 2026-03-18
适用系统: Ubuntu 20.04+, CentOS 7+, Debian 10+