type的选择取决于进程启动方式、就绪判断标准及systemd对服务生命周期的感知能力:type=simple适用于前台常驻进程;type=forking用于传统daemon且需pidfile;type=notify最可靠,要求服务主动发送ready=1信号。

选择 Type= 的关键是看进程如何启动、何时算“就绪”,以及 systemd 如何判断服务是否真正运行成功。不是看程序会不会 fork,而是看 systemd 能否准确感知服务的生命周期。
Type=simple(最常用,默认值)
systemd 认为服务在执行 ExecStart 指定的命令后立即就绪。它不关心进程是否 fork、是否 daemonize,只把主进程 PID 当作服务主体。
适用场景:
- 前台运行的常驻进程(如 nginx -g "daemon off;"、python3 app.py)
- 明确不会 double-fork 的程序
- 你不需要等待服务内部初始化完成(比如监听端口、加载配置)再标记为 active
注意:如果程序自己 fork 成后台守护进程,systemd 会误以为它已退出,导致 unit 状态变成 failed 或 inactive(因为主进程很快结束)。此时不能强行用 simple,得换类型或改启动方式。
Type=forking
专为传统 Unix 守护进程设计。systemd 期望 ExecStart 启动一个“父进程”,该父进程 fork 出子进程后自己退出。systemd 通过追踪 fork 后留下的子进程 PID 来管理服务。
要求必须设置:
-
PIDFile=:指定守护进程写入的 PID 文件路径(systemd 读取它来找到真正的主进程) - 程序必须按约定写 PID 文件,并在 fork 后由子进程持续运行
典型例子:老版本的 Apache httpd、PostgreSQL(启用 pg_ctl start 时)、自定义 shell 脚本启动的 daemon。现在多数新服务已弃用这种模式。
Type=notify
最可靠的方式之一。服务进程启动后先以普通方式运行(不 fork),完成初始化(如绑定端口、加载配置、连接数据库)后,主动通过 sd_notify(3) 向 systemd 发送 "READY=1" 信号。systemd 收到后才将 unit 状态设为 active。
优势明显:
- 避免 race condition(比如依赖它的服务过早启动)
- 支持额外状态通知(如 STATUS=、WATCHDOG=、RELOADING=1)
- 配合 RuntimeDirectory、StateDirectory 等特性更安全
需要程序本身支持 libsystemd(如用 C 写的 systemd-aware 服务),或通过包装器调用 notify(例如 Python 可用 systemd-python,Go 可用 github.com/coreos/go-systemd/v22)。Nginx、Redis、etcd 等现代服务都提供 notify 模式支持。
怎么选?看三点
1. 进程是否自己 daemonize? 是 → 优先考虑 forking(需 PIDFile)或 notify(推荐);否 → simple 或 notify。
2. 你是否需要确保服务“真正可用”后再启动依赖项? 是 → 必须用 notify(simple 和 forking 都无法保证初始化完成)。
3. 程序是否内置 sd_notify 支持? 是 → 直接设 Type=notify;否但可改启动方式(如加 -D 参数禁用 daemonize)→ 改用 simple;否则只能用 forking(并确认 PIDFile 可靠)。










