在 Linux 服务器上运行程序时,如果直接在终端里执行,一旦关闭终端或断开 SSH 连接,程序就会随之退出。要让程序在后台长期稳定运行、开机自启、崩溃后自动恢复,最标准的做法就是把它交给 systemd 管理,安装为一个「服务」。
本文以 Node.js 程序为例,介绍如何将一个程序安装为 systemd 服务。
一、systemd 是什么
systemd 是现代 Linux 发行版(CentOS 7+、Ubuntu 16.04+、Debian 8+ 等)默认的初始化系统,负责在系统启动时拉起各种服务,并对它们进行统一管理。
我们只需要为程序编写一个「服务单元文件」(unit file),告诉 systemd:用什么命令启动、以什么用户运行、崩溃了怎么办,剩下的事情交给 systemd 即可。
二、创建服务单元文件
服务单元文件存放在 /etc/systemd/system/ 目录下,以 .service 结尾。例如创建一个 myapp.service:
sudo vim /etc/systemd/system/myapp.service
写入以下内容:
[Unit]
Description=My Application Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/path/to/app
ExecStart=/usr/bin/node /path/to/app/index.js
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
这个文件分为三个部分:
- [Unit]:描述服务的元信息。
Description是服务描述;After=network.target表示等网络就绪后再启动。 - [Service]:定义服务的运行方式,是核心部分,下面会详细解释。
- [Install]:定义服务如何被启用。
WantedBy=multi-user.target表示在多用户模式(即正常启动模式)下运行。
三、关键配置项说明
| 字段 | 说明 |
|---|---|
Type | 启动类型,simple(默认,ExecStart 进程即主进程)、forking(传统守护进程模式) |
User | 运行服务的用户,如 root 或专门创建的普通用户 |
WorkingDirectory | 进程的工作目录,程序中的相对路径都基于此目录 |
ExecStart | 启动命令,必须写绝对路径 |
Restart | 重启策略:on-failure(异常退出时重启)、always(总是重启)、on-abnormal |
RestartSec | 重启前的等待秒数 |
Environment | 设置环境变量,如 Environment=NODE_ENV=production |
After | 指定启动顺序,在某些 target 或服务之后启动 |
四、常用管理命令
服务文件创建完成后,使用 systemctl 命令进行管理:
# 重新加载配置(修改/新增服务文件后必须执行)
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start myapp
# 停止服务
sudo systemctl stop myapp
# 重启服务
sudo systemctl restart myapp
# 设置开机自启
sudo systemctl enable myapp
# 取消开机自启
sudo systemctl disable myapp
# 查看服务状态
sudo systemctl status myapp
# 实时查看服务日志
sudo journalctl -u myapp -f
# 查看最近 100 行日志
sudo journalctl -u myapp -n 100
五、完整示例:部署 myapp
以一个 Node.js 程序为例,假设代码部署在服务器的 /opt/apps/myapp 目录下。
1. 创建服务文件
sudo vim /etc/systemd/system/myapp.service
内容如下:
[Unit]
Description=My App
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/apps/myapp
ExecStart=/root/.local/share/fnm/node-versions/v24.19.0/installation/bin/node /opt/apps/myapp/index.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
2. 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable myapp
sudo systemctl start myapp
3. 验证运行状态
sudo systemctl status myapp
输出中显示 active (running) 即表示服务正常运行。这样 myapp 就会在系统启动时自动运行,并在崩溃后自动重启。
六、常见坑:ExecStart 找不到 node 命令
很多人的 Node.js 是通过 fnm、nvm 等版本管理工具安装的,写服务文件时如果直接这样写:
ExecStart=node /opt/apps/myapp/index.js
启动服务时会报「找不到 node 命令」的错误。
原因:systemd 启动服务时不会加载 shell 的.bashrc、.profile 等配置文件,所以 PATH 中并不包含 fnm 安装的 node 路径。
解决方法:在 ExecStart 中使用 node 可执行文件的绝对路径。先查出实际路径:
which node
# 输出类似:/root/.local/share/fnm/node-versions/v24.19.0/installation/bin/node
再把该路径填入 ExecStart。或者通过 Environment 显式设置 PATH:
Environment=PATH=/root/.local/share/fnm/aliases/default/bin:/usr/bin:/bin
ExecStart=node /opt/apps/myapp/index.js
注意:使用系统包管理器(apt/yum)安装的 Node.js 通常位于/usr/bin/node,systemd 默认 PATH 就能找到,可以直接写node。
七、小结
将程序安装为 systemd 服务只需要三步:
- 在
/etc/systemd/system/下编写.service单元文件; - 执行
systemctl daemon-reload加载配置; - 用
systemctl enable+systemctl start启用并启动服务。
之后就可以通过 systemctl 统一管理服务,通过 journalctl 查看日志,程序崩溃也会按照 Restart 策略自动恢复,非常适合在服务器上部署 Node.js 应用。