banner
NEWS LETTER

Linux 应用服务化:systemd、日志、开机启动与守护进程

Scroll down

一、为什么要服务化

一个程序能在终端运行,不代表适合部署。真正部署到 Linux 设备或服务器时,需要解决:

  • 开机自动启动。
  • 异常退出自动重启。
  • 统一查看日志。
  • 使用非 root 用户运行。
  • 控制启动顺序。
  • 优雅停止。

Linux 现代发行版通常使用 systemd 管理服务。

二、最小 service 文件

创建:

1
/etc/systemd/system/my_app.service

内容:

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=My App
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/my_app --config /etc/my_app/app.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target

加载:

1
sudo systemctl daemon-reload

启动:

1
sudo systemctl start my_app

查看状态:

1
systemctl status my_app

开机启动:

1
sudo systemctl enable my_app

三、查看日志

查看最近日志:

1
journalctl -u my_app -n 100

实时日志:

1
journalctl -u my_app -f

按时间过滤:

1
journalctl -u my_app --since "2026-06-21 10:00:00"

如果程序把日志输出到 stdout/stderr,systemd 会自动收集到 journal。

四、优雅停止

停止服务:

1
sudo systemctl stop my_app

systemd 默认会发送 SIGTERM。程序应该捕获 SIGTERM,完成资源清理后退出。

应用中需要处理:

  • 停止接收新请求。
  • 保存必要状态。
  • 关闭文件。
  • 关闭 socket。
  • 等待工作线程退出。

不要依赖 kill -9SIGKILL 无法清理资源。

五、使用非 root 用户

创建用户:

1
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp

service:

1
2
3
4
[Service]
User=myapp
Group=myapp
ExecStart=/usr/local/bin/my_app --config /etc/my_app/app.conf

目录权限:

1
2
sudo mkdir -p /var/lib/my_app /var/log/my_app
sudo chown -R myapp:myapp /var/lib/my_app /var/log/my_app

服务不应该默认用 root 跑。只有确实需要特权端口、硬件访问或系统配置时,才考虑授权。

六、环境变量

可以在 service 中设置:

1
2
3
[Service]
Environment=APP_ENV=prod
Environment=LOG_LEVEL=info

也可以使用环境文件:

1
2
[Service]
EnvironmentFile=/etc/my_app/my_app.env

/etc/my_app/my_app.env

1
2
APP_ENV=prod
LOG_LEVEL=info

七、重启策略

常见配置:

1
2
3
4
Restart=on-failure
RestartSec=3
StartLimitIntervalSec=60
StartLimitBurst=5

含义:

  • 失败时重启。
  • 3 秒后重启。
  • 60 秒内最多尝试 5 次。

这样可以避免程序一直崩溃、systemd 疯狂拉起。

八、常见排错

8.1 service 修改后没生效

执行:

1
2
sudo systemctl daemon-reload
sudo systemctl restart my_app

8.2 手动能运行,systemd 不能运行

常见原因:

  • 工作目录不同。
  • 环境变量不同。
  • 权限不同。
  • 相对路径失效。

建议在 service 中使用绝对路径:

1
2
WorkingDirectory=/opt/my_app
ExecStart=/opt/my_app/bin/my_app --config /etc/my_app/app.conf

8.3 日志不足

先看:

1
journalctl -u my_app -n 200 --no-pager

程序启动时应该打印配置路径、监听端口、版本号和关键依赖状态。

九、推荐 service 模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=My App
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/my_app
EnvironmentFile=-/etc/my_app/my_app.env
ExecStart=/opt/my_app/bin/my_app --config /etc/my_app/app.conf
Restart=on-failure
RestartSec=3
StartLimitIntervalSec=60
StartLimitBurst=5

[Install]
WantedBy=multi-user.target

EnvironmentFile 前面的 - 表示文件不存在也不算失败。

十、总结

服务化不是把程序丢到后台运行。一个合格的 Linux 服务需要可启动、可停止、可重启、可观察、可排错。

systemd 是部署 Linux 应用的基础工具。掌握它以后,应用从“能跑”到“能长期稳定运行”会跨过一大步。

其他文章
目录导航 置顶
  1. 1. 一、为什么要服务化
  2. 2. 二、最小 service 文件
  3. 3. 三、查看日志
  4. 4. 四、优雅停止
  5. 5. 五、使用非 root 用户
  6. 6. 六、环境变量
  7. 7. 七、重启策略
  8. 8. 八、常见排错
    1. 8.1. 8.1 service 修改后没生效
    2. 8.2. 8.2 手动能运行,systemd 不能运行
    3. 8.3. 8.3 日志不足
  9. 9. 九、推荐 service 模板
  10. 10. 十、总结
请输入关键词进行搜索