systemd
是现代 Linux 发行版的标准初始化系统和服务管理器。我们通过创建一个 服务单元文件(Service Unit File) 来实现所需的功能。
整体步骤概览
- 准备你的应用程序:确保你的应用已经安装或编译好,知道其启动命令和所需的工作目录。
- 创建 Service 文件:在
/etc/systemd/system/
目录下创建一个以.service
结尾的文件。 - 设置文件和目录权限:确保
systemd
有权限执行你的应用和相关文件。 - 重载 systemd 配置:让
systemd
识别新的服务文件。 - 启动并测试服务:启动服务,检查状态,测试功能。
- 启用开机自启:配置服务在系统启动时自动运行。
- (可选)查看日志:学习如何排查问题。
第1步:准备应用程序
假设你的应用是一个名为 myapp
的二进制文件,放在 /opt/myapp/
目录下。
启动命令为:/opt/myapp/myapp --config /opt/myapp/config.conf
- 最佳实践:
- 将你的应用程序放在
/opt
,/srv
或/usr/local/bin
等标准位置。 - 如果应用会产生日志,建议让它输出到
stdout
/stderr
,由systemd
统一捕获和管理,而不是自己写日志文件。 - 确保应用不会自行“守护进程化”(daemonize/fork into the background),
systemd
更适合管理前台进程。
- 将你的应用程序放在
第2步:创建 Service 文件
使用 sudo
权限在 /etc/systemd/system/
目录下创建服务文件,例如 myapp.service
。
sudo vi /etc/systemd/system/myapp.service |
将以下内容粘贴到文件中,并根据你的实际情况进行修改。
[Unit] |
第3步:设置权限
为应用文件设置权限:
# 假设你创建了一个名为 ‘appuser’ 的用户来运行此服务
sudo useradd -r -s /bin/false appuser # 创建系统用户,无需登录shell
sudo chown -R appuser:appgroup /opt/myapp # 将应用目录的所有权给该用户
sudo chmod -R 750 /opt/myapp # 设置合适的权限Service 文件权限:通常 root ownership 和 644 权限即可,
systemctl
会自动处理。
第4步:重载 systemd 配置
创建或修改服务文件后,必须让 systemd
重新加载其配置。sudo systemctl daemon-reload
第5步:启动并测试服务
启动服务:
sudo systemctl start myapp
检查服务状态:这是最重要的调试命令。
sudo systemctl status myapp
- 如果状态是
active (running)
,表示启动成功。 - 如果失败, status 命令通常会显示最近的错误信息。
- 如果状态是
测试自动重启:
- 手动杀掉你的应用进程:
sudo pkill myapp
- 等待几秒(我们设置了
RestartSec=5
),再次运行sudo systemctl status myapp
。你应该会看到服务的 Active 时间更新了,并且日志里可能有重启的记录。
- 手动杀掉你的应用进程:
第6步:启用开机自启
sudo systemctl enable myapp |
这个命令会在 /etc/systemd/system/multi-user.target.wants/
目录下创建一个符号链接,指向你的服务文件。这样系统启动时就会自动启动该服务。
验证是否启用:sudo systemctl is-enabled myapp
# 应返回 ‘enabled’
第7步:查看应用日志
systemd
使用 journalctl
统一管理所有服务的日志。
查看该服务的全部日志:
sudo journalctl -u myapp
实时追踪最新日志(类似
tail -f
):sudo journalctl -u myapp -f
查看本次启动以来的日志:
sudo journalctl -u myapp -b
查看日志并显示更详细的时间戳:
sudo journalctl -u myapp --since "2024-01-01 12:00:00"
Service 脚本各部分含义详解
[Unit] 部分
Description
: 对人类友好的服务描述文本。Documentation
: 提供项目文档的 URL,方便维护者查阅。After
: 定义启动顺序的依赖关系。After=network.target
表示“在 network.target 单元之后启动”,确保网络可用后再启动你的网络应用。
[Service] 部分(核心)
Type
:simple
(默认): 假设ExecStart
命令是主进程,并且会一直在前台运行。forking
: 假设ExecStart
命令会调用fork()
创建子进程,然后父进程退出。systemd
需要跟踪子进程。常用于传统的守护进程。exec
: 类似simple
,但在执行完ExecStart
命令后,systemd
才会认为服务启动完成。
User
/Group
: 安全最佳实践。以最小权限的非 root 用户运行服务,减少被攻击后的影响面。WorkingDirectory
: 在运行程序前,切换到此目录。这样你的应用就可以使用相对路径(如./config.conf
)来访问文件。ExecStart
: 最关键的指令。指定启动服务的完整命令和参数。Restart
: 自动重启策略。no
: 从不重启。on-failure
: 仅在进程以非零退出码终止时重启(推荐用于大多数情况)。always
: 无论什么原因退出,总是重启(适合必须持续运行的服务)。on-abort
: 仅在收到未处理的信号而终止时重启。
RestartSec
: 在尝试重启服务前,systemd
等待的时间。防止频繁崩溃时不断快速重启加重系统负担。Environment
: 设置环境变量,格式为KEY=VAL
。EnvironmentFile
: 指定一个文件(如/etc/default/myapp
),该文件包含KEY=VAL
格式的环境变量。在文件中管理配置比直接在 service 文件中写更清晰。
[Install] 部分
WantedBy
: 指定服务安装在哪个“目标(target)”下。multi-user.target
是标准的无图形界面的多用户命令行模式。当您执行systemctl enable myapp
时,就是在为这个WantedBy
关系创建符号链接。