我有一个节点应用程序,通过 Ubuntu 16.04 上的 systemd 服务运行
然而,一段时间后该服务会自动重新启动。
以下是我在日志中得到的内容:
Mar 17 14:35:10 testmachine systemd[1]: myService.service: Main process exited, code=exited, status=7/NOTRUNNING
Mar 17 14:35:10 testmachine systemd[1]: myService.service: Unit entered failed state.
Mar 17 14:35:10 testmachine systemd[1]: myService.service: Failed with result 'exit-code'.
Mar 17 14:35:40 testmachine systemd[1]: myService.service: Service hold-off time over, scheduling restart.
据我了解,systemd 检测到服务未运行,并在 30 秒后重新启动,正如我在服务配置文件中指定的一样。
我的服务.服务
[Unit]
Description=The will start node app
After=cleanMongo.service
[Service]
ExecStart=/media/path/to/execution/scriptFile
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target
但我的问题是,为什么它认为服务没有运行?应用程序正在执行其任务,但在中间它重新启动了。
附言:我在节点应用程序中运行了许多 CRON 作业,是不是因为进程太忙而无法回复来自isAlive
systemd 的某些信息?这就是为什么 systemd 认为它没有运行?
答案1
通常,systemd/systemctl 会报告启动失败(如果/当您运行sudo systemctl start myService.service
)。
我会检查:
- 输出
sudo systemctl status myService.service
- 输出
sudo journalctl -ln 2000 -u myService
两者的输出都可能有助于诊断问题(journalctl 可能是更好的选择)。
同样值得尝试的是复制你的 systemd 服务单元正在做的事情 - 例如尝试从交互式会话(可能使用 sudo)运行相同的命令并查看报告了哪些错误。
systemd/systemctl 实际上跟踪 PID,因此轮询不应该成为问题。
更新根据您的服务定义,运行包装脚本可能是问题的一部分。
您的 systemd 配置希望能够通过 PID 跟踪进程本身。但是,它会“看到”脚本的 PID,但根据您从该脚本运行节点的方式,它可能无法跟踪节点的 PID。
似乎更可靠的方法是直接运行节点(如建议的那样这里):
[Unit]
Description=Node.js Example Server
#Requires=After=mysql.service # Requires the mysql service to run first
[Service]
ExecStart=/usr/local/bin/node /opt/nodeserver/server.js
#WorkingDirectory=/opt/nodeserver # Required on some systems
Restart=always
RestartSec=10 # Restart service after 10 seconds if node service crashes
StandardOutput=syslog # Output to syslog
StandardError=syslog # Output to syslog
SyslogIdentifier=nodejs-example
#User=<alternate user>
#Group=<alternate group>
Environment=NODE_ENV=production PORT=1337
[Install]
WantedBy=multi-user.target
这样,systemd 就能够跟踪正确的 PID。
如果您需要在运行节点之前运行一些命令,请考虑使用 systemd 的ExecStartPre
。
systemd 还提供了许多其他选项(请参阅单元文件您可以使用 man 页面来避免使用包装器:
- 如上所述,
ExecStartPre
允许您在主进程启动之前执行任务(以及ExecStartPost
在启动之后执行任务) Require
您可以通过、、和来表达对其他服务的依赖关系Wants
,也可以使用或各种关键字。Before
After
Conflicts
Condition*
答案2
首先,我不是nodejs专家。
正如其他人所说,您应该尽可能多地将 移动到 systemd 单元中。cd
可以用 sudo 替换,WorkingDirectory
这是没用的,但可以用 替换User
,环境变量可以用 来设置Environment
。
Type
如果is != notify
(默认为simple
),Systemd 不会等待来自守护进程的任何“isAlive”调用
这NOTRUNNING
是对你进程的退出代码的解释,这意味着你的节点进程以错误代码 7 退出节点文档说退出代码意味着“存在未捕获的异常,并且内部致命异常处理程序函数本身在尝试处理该异常时引发了错误。”因此在日志或者nodejs的日志目的地应该有一些输出。