systemd 单元里那些容易踩的坑
Type=notify 在等什么
Type=notify 要求进程自己往 $NOTIFY_SOCKET 发 READY=1。进程不发的后果不是
立刻失败,而是卡在 activating 直到 TimeoutStartSec 超时,然后被判定为
Failed with result 'timeout'——期间端口可能已经监听了,服务看起来“又活着又死了”。
排查顺序:先看 systemctl status 的 Active 状态,再看 ss -tlnp 是否在听。
两者矛盾,基本就是 notify 没发。把 Type 改成 simple 通常立刻正常。
Restart= 的语义
Restart=no # 不重启
Restart=on-failure # 非 0 退出、被信号杀、超时 —— 会重启
Restart=always # 除 systemctl stop 之外都重启
配合 RestartSec=5 是常规写法。但要留意 StartLimitIntervalSec 与
StartLimitBurst:默认 10 秒内失败 5 次就会进入 failed 且不再重启,
日志里那句 start request repeated too quickly 指的就是这个。
沙箱选项会悄悄改行为
ProtectSystem=strict 让整个文件系统只读,只剩 /dev、/proc、/sys;
PrivateTmp=true 给进程一个独立的 /tmp。这两个加上去之后,程序写临时文件、
建锁文件都可能失败,而报错信息往往只说 “permission denied”。
建议做法:加沙箱之前先用 strace -f -e trace=openat 跟一遍,看它到底碰了哪些路径,
再决定用 ReadWritePaths= 开哪几个口子。比事后猜日志快得多。
最后一点
systemctl daemon-reload 只在你改了 unit 文件本身时才需要;改的是
/etc/default/ 里的环境变量就不用。这条搞混过好几次,记一下。