导语:在 Ubuntu 24.04 LTS 上部署 Web 服务、定时脚本、后台队列或自研守护进程时,最常见的需求就是“开机自动启动”和“出问题能快速看日志”。Ubuntu 24.04 LTS 使用 systemd 作为初始化与服务管理体系,发布说明中也明确该版本更新到 systemd v255.4,适合用标准 unit 文件来管理服务生命周期 官方发布说明。🚀
一、先理解 systemd 服务的基本结构
systemd 的服务配置通常以 .service 结尾,文件内容描述一个进程如何被启动、停止、重启以及如何加入开机流程。按照 systemd.service 手册,通用配置主要放在 [Unit] 与 [Install] 段,服务相关配置放在 [Service] 段 systemd.service 手册。
自定义服务一般建议放在 /etc/systemd/system/ 目录,而不是直接修改系统包自带的 /lib/systemd/system/ 文件。前者适合管理员维护,升级系统软件时也更不容易被覆盖。一个典型场景是让 /opt/myapp/app.sh 在开机后自动运行,并在异常退出时自动重启。
二、创建一个可自启动的服务文件 ⚙️
可以新建 /etc/systemd/system/myapp.service,内容示例如下:
[Unit]
Description=My App Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/bash /opt/myapp/app.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
这里的 Description 用于说明服务用途;After=network-online.target 表示尽量在网络就绪后启动;User 指定服务运行用户,避免长期使用 root;WorkingDirectory 指定工作目录;ExecStart 是真正执行的命令;Restart=on-failure 表示进程异常退出时重启。Type=simple 适合大多数前台常驻程序,因为 systemd 会把 ExecStart 启动的进程视为主进程。
三、加载、启动与设置开机自启
创建或修改 unit 文件后,需要让 systemd 重新读取配置:
sudo systemctl daemon-reload
然后可以立刻启动服务,并检查状态:
sudo systemctl start myapp.service
systemctl status myapp.service
确认运行正常后,执行以下命令加入开机自启:
sudo systemctl enable myapp.service
如果希望现在启动并同时设置自启,也可以使用:
sudo systemctl enable --now myapp.service
取消自启动则使用:
sudo systemctl disable myapp.service
四、排查启动失败的常见原因 🔍
1. ExecStart 路径错误
systemd 不会像交互式 shell 那样自动加载你的 .bashrc,因此路径要尽量写绝对路径。例如不要只写 python、node 或 bash,推荐写 /usr/bin/python3、/usr/bin/node、/usr/bin/bash。可以用 which python3 或 command -v node 先确认程序位置。
2. 权限不足
如果服务以 User=ubuntu 运行,就要确认该用户能读取程序文件、进入工作目录、写入日志目录。常见修复方式包括调整文件属主、目录权限,或把运行数据目录放到 /var/lib/myapp、日志目录放到 /var/log/myapp。
3. 网络或依赖服务未就绪
有些程序启动时需要数据库、Redis 或网络。如果只是写 After=network.target,可能并不代表网络完全可用。对于依赖网络连接的服务,可以考虑 After=network-online.target 与 Wants=network-online.target,但仍建议应用自身具备重试机制。
4. 脚本依赖环境变量
手动运行正常,systemd 启动失败,很多时候是环境变量不同导致的。可以在 [Service] 中添加 Environment=APP_ENV=production,或者使用 EnvironmentFile=/etc/myapp/myapp.env 来集中管理变量。注意环境文件中不要随意放宽权限,尤其是包含密钥时。
五、用 journalctl 查看服务日志 📘
journalctl 是查看 systemd journal 日志的标准工具。根据 journalctl 手册,它可以读取 systemd-journald 保存的日志,并通过 unit、时间、优先级等条件过滤 journalctl 手册。
查看某个服务的全部日志:
journalctl -u myapp.service
只看最近 100 行:
journalctl -u myapp.service -n 100
实时跟踪日志,适合边启动边观察:
journalctl -u myapp.service -f
查看本次启动以来的日志:
journalctl -u myapp.service -b
按时间范围过滤:
journalctl -u myapp.service --since "2026-08-18 08:00" --until "2026-08-18 09:00"
只看错误级别及以上日志:
journalctl -u myapp.service -p err
六、让日志更容易定位问题
如果程序直接向标准输出和标准错误打印日志,systemd 通常会把这些内容收进 journal。对于自研脚本,建议启动、加载配置、连接数据库、监听端口、捕获异常时都输出清晰信息。不要只打印“failed”,而应说明失败动作、关键参数和错误原因。
还可以在服务文件中显式设置日志标识:
[Service]
SyslogIdentifier=myapp
这样在 journal 中更容易通过关键字识别日志来源。若服务频繁重启,可以结合 systemctl status myapp.service 查看 Main PID、退出码、最近日志片段,再用 journalctl -u myapp.service -b 拉取完整上下文。
七、生产环境建议 ✅
- 使用普通用户运行:除非确有必要,不要让业务服务长期以 root 身份运行。
- 使用绝对路径:ExecStart、脚本路径、配置路径都尽量写完整。
- 配置自动重启:Restart=on-failure 适合多数后台服务,但不要掩盖程序本身的崩溃原因。
- 保留可读日志:关键错误要输出到 stdout 或 stderr,便于 journalctl 统一查看。
- 修改后重新加载:每次改 unit 文件后执行 systemctl daemon-reload,再 restart 服务。
- 谨慎设置依赖:After 只控制启动顺序,不等同于强依赖;需要强依赖时再评估 Requires 或 Wants。
总结 🎯
在 Ubuntu 24.04 LTS 中,使用 systemd 配置服务自启动的核心流程并不复杂:编写 .service 文件、执行 daemon-reload、启动服务、检查状态、enable 设置开机自启。真正拉开运维效率差距的,是能否写出清晰的 ExecStart、合理的运行用户、必要的重启策略,以及熟练使用 journalctl 按服务、时间和级别过滤日志。
如果服务启动失败,不要急着反复重启。先看 systemctl status,再用 journalctl -u 服务名 -b 追溯本次启动日志,重点检查路径、权限、环境变量、依赖服务和程序自身报错。把这些基础动作养成习惯,Ubuntu 24.04 LTS 上的大多数 systemd 自启动与日志问题都能快速定位。🛠️