Linux Systemd 服务注册指南
一、什么是 Systemd
Systemd 是 Linux 系统的初始化系统和服务管理器,负责管理系统启动过程中的所有服务(称为"单元")。每个服务对应一个 .service 单元文件,通过 systemctl 命令进行管理。
二、创建服务单元文件
服务单元文件通常放在以下两个目录之一:
| 目录 | 说明 |
|---|---|
/etc/systemd/system/ |
推荐,管理员自定义服务,优先级最高 |
/usr/lib/systemd/system/ |
软件包安装时自动放置,不建议手动修改 |
创建命令:
sudo vim /etc/systemd/system/myapp.service
文件名建议与你的服务名保持一致,后缀必须为
.service
三、编写服务配置
一个标准的 .service 文件包含三个区块:[Unit]、[Service]、[Install]。
3.1 基本模板
[Unit]
Description = My Application Service
After = network.target
[Service]
Type = simple
ExecStart = /usr/bin/python3 /opt/myapp/app.py
WorkingDirectory = /opt/myapp
User = www-data
Group = www-data
Restart = on-failure
RestartSec = 5
StandardOutput = journal
StandardError = journal
[Install]
WantedBy = multi-user.target
3.2 字段详解
[Unit] 区块 — 描述与依赖
| 字段 | 说明 | 示例 |
|---|---|---|
Description |
服务描述 | Description=My Web App |
After |
在哪些服务之后启动 | After=network.target |
Requires |
强依赖(依赖失败则本服务也终止) | Requires=postgresql.service |
Wants |
弱依赖(依赖失败不影响本服务) | Wants=network-online.target |
[Service] 区块 — 运行方式
| 字段 | 说明 | 可选值/示例 |
|---|---|---|
Type |
服务类型 | simple(默认,前台进程)、forking(守护进程)、oneshot(一次性任务) |
ExecStart |
启动命令(必须用绝对路径) | ExecStart=/usr/bin/node /opt/app/server.js |
ExecStop |
停止命令(可选,默认发送 SIGTERM) | ExecStop=/bin/kill -SIGTERM $MAINPID |
ExecReload |
重载配置命令 | ExecReload=/bin/kill -HUP $MAINPID |
WorkingDirectory |
工作目录 | WorkingDirectory=/opt/myapp |
User / Group |
运行用户和组(建议非 root) | User=www-data |
Restart |
重启策略 | no、on-failure、always、on-abnormal |
RestartSec |
重启间隔秒数 | RestartSec=5 |
Environment |
环境变量 | Environment="NODE_ENV=production" |
EnvironmentFile |
从文件读取环境变量 | EnvironmentFile=/opt/myapp/.env |
StandardOutput |
标准输出方式 | journal、file:/var/log/myapp.log |
StandardError |
标准错误输出方式 | journal、file:/var/log/myapp-error.log |
LimitNOFILE |
文件描述符限制 | LimitNOFILE=65535 |
[Install] 区块 — 安装目标
| 字段 | 说明 | 示例 |
|---|---|---|
WantedBy |
关联到哪个 target | WantedBy=multi-user.target |
RequiredBy |
强依赖安装目标 | RequiredBy=graphical.target |
常见 target:
multi-user.target:多用户文本模式(服务器常用)graphical.target:图形界面模式
四、注册与启动服务
修改或创建 .service 文件后,按以下步骤操作:
# 1. 重载 systemd 配置(每次修改 .service 文件后必须执行)
sudo systemctl daemon-reload
# 2. 启动服务
sudo systemctl start myapp
# 3. 设置开机自启
sudo systemctl enable myapp
# 4. 查看服务状态
systemctl status myapp
快捷方式:
sudo systemctl enable --now myapp可以一步完成"启用 + 启动"
五、常用管理命令
# 启动服务
sudo systemctl start myapp
# 停止服务
sudo systemctl stop myapp
# 重启服务
sudo systemctl restart myapp
# 重载配置(不重启进程,需要 Service 中配置了 ExecReload)
sudo systemctl reload myapp
# 设置开机自启
sudo systemctl enable myapp
# 取消开机自启
sudo systemctl disable myapp
# 查看服务状态
systemctl status myapp
# 重载 systemd 配置
sudo systemctl daemon-reload
# 查看服务是否已启用
systemctl is-enabled myapp
# 查看服务是否正在运行
systemctl is-active myapp
六、日志查看
Systemd 使用 journald 统一管理日志:
# 实时查看服务日志(类似 tail -f)
journalctl -u myapp -f
# 查看最近 100 行日志
journalctl -u myapp -n 100
# 查看最近 1 小时的日志
journalctl -u myapp --since "1 hour ago"
# 查看今天的日志
journalctl -u myapp --since today
# 查看指定时间范围的日志
journalctl -u myapp --since "2024-01-01 00:00:00" --until "2024-01-02 00:00:00"
# 查看错误级别以上的日志
journalctl -u myapp -p err
# 查看上次启动以来的日志
journalctl -u myapp -b
七、常见问题排查
问题 1:服务启动失败
# 查看详细错误日志
journalctl -u myapp -xe
# 查看服务状态
systemctl status myapp
常见原因:
- 路径错误:
ExecStart必须使用绝对路径 - 权限不足: 检查
User是否有权限访问工作目录和可执行文件 - 端口占用: 检查端口是否已被其他服务占用
- 依赖服务未启动: 检查
After和Requires中的依赖服务是否正常运行
问题 2:修改配置不生效
每次修改 .service 文件后,必须执行:
sudo systemctl daemon-reload
sudo systemctl restart myapp
问题 3:脚本无法执行
确保脚本有可执行权限:
chmod +x /opt/myapp/start.sh
如果 ExecStart 中需要使用管道、重定向等 shell 语法,需要用 /bin/bash -c 包裹:
ExecStart=/bin/bash -c "/opt/myapp/start.sh | tee /var/log/myapp.log"
问题 4:服务反复重启
检查 Restart 和 RestartSec 配置,适当增加重启间隔:
Restart=on-failure
RestartSec=10
八、完整示例
示例 1:Python Flask 应用
[Unit]
Description = Flask Web Application
After = network.target
[Service]
Type = simple
User = www-data
Group = www-data
WorkingDirectory = /opt/flask-app
Environment = "FLASK_ENV=production"
ExecStart = /opt/flask-app/venv/bin/python /opt/flask-app/app.py
Restart = on-failure
RestartSec = 5
StandardOutput = journal
StandardError = journal
[Install]
WantedBy = multi-user.target
示例 2:Node.js 应用
[Unit]
Description = Node.js Application
After = network.target
[Service]
Type = simple
User = node
Group = node
WorkingDirectory = /opt/node-app
Environment = "NODE_ENV=production"
ExecStart = /usr/bin/node /opt/node-app/server.js
Restart = on-failure
RestartSec = 5
LimitNOFILE = 65535
StandardOutput = journal
StandardError = journal
[Install]
WantedBy = multi-user.target
示例 3:Shell 脚本服务
[Unit]
Description=My Shell Script Service
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/scripts/backup.sh
Restart=on-failure
RestartSec=10
StandardOutput=file:/var/log/backup.log
StandardError=file:/var/log/backup-error.log
[Install]
WantedBy=multi-user.target
示例 4:Java Spring Boot 应用
[Unit]
Description=Spring Boot Application
After=network.target
[Service]
Type=simple
User=java
Group=java
WorkingDirectory=/opt/spring-app
ExecStart=/usr/bin/java -jar /opt/spring-app/app.jar
Restart=on-failure
RestartSec=10
Environment="JAVA_OPTS=-Xms512m -Xmx1024m"
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
示例 5:Go 开发的可执行二进制应用
[Unit]
Description=Pulse Agent
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/pulse-agent
Restart=on-failure
RestartSec=5s
Environment="PULSE_SERVER=$SERVER_URL"
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
快速操作清单
# 1. 创建服务文件
sudo vim /etc/systemd/system/myapp.service
# 2. 重载配置
sudo systemctl daemon-reload
# 3. 启用并启动
sudo systemctl enable --now myapp
# 4. 查看状态
systemctl status myapp
# 5. 查看日志
journalctl -u myapp -f
提示:将上述模板中的
myapp替换为你的实际服务名,将路径和命令替换为你的实际配置即可直接使用。

浙公网安备 33010602011771号