Systemd - 如何从使用无密码 sudo 的用户空间重新启动节点进程

Systemd - 如何从使用无密码 sudo 的用户空间重新启动节点进程

我有一个以非root 用户身份运行的nodejs 进程(并且需要这样做是有原因的),但它有一个依赖项,需要root 访问权限才能访问raspberry pi gpio 中断。所以解决方案是我gpio在 rpi 上有一个组,其中包含用于运行节点的 sudoers 条目。然后我用服务单元文件启动这个脚本,它工作正常

[Unit]
Description=switches16-mcp230xx-dSxJM-interrupt Device Starter Service
After=network-online.target

[Service]
Environment=UCI_ENV=pro
ExecStart=/usr/bin/sudo /usr/bin/node -r esm /opt/light/switches16-mcp230xx-dSxJM-interrupt/index.js
Restart=on-failure
WorkingDirectory=/opt/light/switches16-mcp230xx-dSxJM-interrupt

[Install]
WantedBy=default.target

问题出现在重新启动(或失败重新启动)时。该进程需要被终止,但它是作为 sudo 启动的,所以毫不奇怪,它也必须使用 sudo 终止。

Mar 12 19:43:12 switches systemd[1289]: switches16-mcp230xx-dSxJM-interrupt.service: Failed to kill main process 11222 (sudo), ignoring: Operation not permitted
Mar 12 19:43:12 switches systemd[1289]: switches16-mcp230xx-dSxJM-interrupt.service: Killing process 11223 (node) with signal SIGKILL.
Mar 12 19:43:12 switches systemd[1289]: switches16-mcp230xx-dSxJM-interrupt.service: Failed to kill control group /user.slice/user-1000.slice/[email protected]/switches16-mcp230xx-dSxJM-

因此,由于单元文件是作为非 root 用户启动的,所以它会作为用户杀死,所以我假设我必须在启动它时故意使用 sudo 杀死该进程。所以我添加了这个。

ExecReload=/usr/bin/sudo /bin/kill -HUP $MAINPID

但得到了同样的错误。即使我的 sudoers.d 文件有

%gpio ALL=NOPASSWD: /usr/bin/node
%gpio ALL=NOPASSWD: /bin/kill

我一定在这里遗漏了一些东西,但我无法指出它。

这是单元文件产生的进程,必须在重新启动之前终止

root     11093  0.0  0.3   8468  2920 ?        Ss   18:01   0:00  \_ /usr/bin/sudo /usr/bin/node -r esm /opt/light/switches16-mcp230xx-dSxJM-interrupt/index.js
root     11094  6.7  4.8 142820 45788 ?        SLl  18:01   6:52      \_ /usr/bin/node -r esm /opt/light/switches16-mcp230xx-dSxJM-interrupt/index.js

有什么建议么?

让我重申一下,我无法以 root 身份运行此服务,因此没有必要提出这样的建议,因为这显然是一个简单的答案。我正在部署此代码并通过 ssh 启动,无需 root 访问密钥,因此以无密码 sudo 的用户身份运行是我唯一的选择。如果我的代码中没有这种特定的硬件(根)依赖性,我根本不会遇到这个问题。

相关内容