ExecStopPost进程缺失EXIT_CODE环境变量,SSL证书更新后程序重启遇阻
解决systemd ExecStopPost缺失EXIT_CODE等环境变量的问题
我之前在配置acme-tiny自动更新证书后重启服务时,也碰到过一模一样的坑!明明照着systemd手册说的应该有$EXIT_CODE、$SERVICE_RESULT这些变量,但实际就是找不到,折腾了半天才搞清楚原因,给你分享下解决方案:
核心原因:systemd追踪的进程不对
这些环境变量只有在systemd直接追踪到服务主进程的退出状态时才会被设置。如果你的acme-tiny服务是通过shell脚本、bash -c这类方式启动的,systemd实际监控的是shell进程,而不是acme-tiny本身,这时候传递给ExecStopPost的是shell的退出码,甚至可能因为shell的默认行为导致变量根本没生成。
分步解决方法
1. 修正服务的Type和ExecStart配置
首先确保你的acme-tiny.service主配置里:
- 设置
Type=exec(这是关键!):这个类型会让systemd直接启动指定的进程,而不是通过shell中转,能准确追踪主进程的退出状态。 - 直接调用acme-tiny,不要用shell包裹:
坏例子:
好例子:ExecStart=/bin/bash -c "/usr/local/bin/acme-tiny --account-key /path/to/key --csr /path/to/csr --acme-dir /var/www/challenges > /path/to/cert.crt"Type=exec ExecStart=/usr/local/bin/acme-tiny --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /path/to/domain.crt
2. 如果必须用脚本包裹,用exec替换进程
如果确实需要前置/后置操作(比如创建临时目录、备份旧证书),那在脚本的最后一行用exec调用acme-tiny,这样shell进程会被acme-tiny替换,systemd依然能追踪到正确的进程:
#!/bin/bash # 这里放你的前置操作,比如备份旧证书 cp /path/to/domain.crt /path/to/domain.crt.bak # 用exec替换当前shell进程为acme-tiny exec /usr/local/bin/acme-tiny --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /path/to/domain.crt
3. 验证环境变量是否正常生成
在你的cert_reload.conf里先加个调试命令,确认变量存在:
[Service] ExecStopPost=/bin/sh -c 'echo "SERVICE_RESULT=$SERVICE_RESULT EXIT_CODE=$EXIT_CODE EXIT_STATUS=$EXIT_STATUS" >> /var/log/acme-debug.log'
然后手动触发一次服务:
systemctl start acme-tiny.service
查看/var/log/acme-debug.log,如果能看到变量值,说明配置生效了。
4. 配置成功后重启目标服务
确认变量正常后,修改ExecStopPost只在acme-tiny成功退出(EXIT_CODE=0)时重启你的服务:
[Service] ExecStopPost=/bin/sh -c 'if [ "$EXIT_CODE" -eq 0 ]; then systemctl restart your-target-service.service; fi'
额外注意事项
- 确保你的acme-tiny服务设置了
Restart=no,避免服务自动重启干扰逻辑。 EXIT_CODE是进程的纯退出码(0表示成功),而EXIT_STATUS包含信号信息(比如被kill的话是128+信号数),判断成功用EXIT_CODE更准确。
内容的提问来源于stack exchange,提问作者VPfB
相关产品推荐
相关产品推荐

