You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Systemd启动Node.js程序时部分exec()调用失效问题求助

问题排查:systemd服务下Node.js程序部分exec命令失效

问题描述

Ubuntu环境下开发的Node.js程序,直接运行时所有exec()调用的Shell命令均正常工作,但注册为systemd服务(服务名speaker)后,仅/usr/local/bin/gpio相关命令正常,/usr/bin/amixer、/usr/bin/firefox等命令全部失效。

相关配置与代码

systemd服务配置(/etc/systemd/system/speaker.service)

[Service]
ExecStart=/home/speaker/speakerModule/start.sh
WorkingDirectory=/home/speaker/speakerModule
User=speaker

[Install]
WantedBy=multi-user.target

启动脚本(/home/speaker/speakerModule/start.sh)

#!/bin/bash /home/speaker/.nvm/versions/node/v18.13.0/bin/node speaker.js

Node.js核心代码片段

function setVolume(volume) {
  if (volume < 0 || volume > 100) return;
    if (volume === 0) {
        exec(`/usr/local/bin/gpio -g write ${RELAY} 0`);
  } else {
        exec(`/usr/local/bin/gpio -g write ${RELAY} 1`);
  }
  exec(`/usr/bin/amixer -D pulse sset Master ${volume}%`);
}

// ...其他代码

setVolume(30);
socket.connect();
exec(`/usr/local/bin/gpio -g mode ${RELAY} out`);
exec(`/usr/bin/firefox ${PLAYER_CONTROL_ENDPOINT}`);

问题原因分析

  1. 启动脚本格式错误:start.sh的Shebang行写法错误,#!/bin/bash后直接拼接Node命令不符合Shell脚本规范,导致脚本执行逻辑异常。
  2. systemd服务的环境缺失:
    • multi-user.target下无桌面会话,firefox需要X11显示环境才能启动;
    • amixer依赖PulseAudio的用户会话,systemd服务默认没有加载该会话的环境变量;
    • systemd服务的默认环境变量集远小于普通用户会话,部分命令依赖的隐性环境未配置。
  3. 错误处理缺失:Node.js的exec()调用未添加错误回调,无法捕获命令执行失败的具体原因,增加排查难度。

解决方案

1. 修复启动脚本格式

修改start.sh为标准Shell脚本格式:

#!/bin/bash
/home/speaker/.nvm/versions/node/v18.13.0/bin/node speaker.js

2. 调整systemd服务配置

更新/etc/systemd/system/speaker.service,补充环境变量与会话支持:

[Service]
ExecStart=/home/speaker/speakerModule/start.sh
WorkingDirectory=/home/speaker/speakerModule
User=speaker
# 配置X11显示与音频会话环境
Environment=DISPLAY=:0
Environment=XAUTHORITY=/home/speaker/.Xauthority
Environment=PULSE_SERVER=/run/user/$(id -u speaker)/pulse/native
# 确保服务启动前等待桌面环境就绪
PermissionsStartOnly=true
ExecStartPre=/bin/sleep 5
# 自动重启服务
Restart=always

[Install]
# 改为依赖桌面会话目标
WantedBy=graphical.target

3. 配置用户权限

允许speaker用户访问X11桌面:

xhost +local:speaker

4. 为exec调用添加错误处理

修改Node.js代码中的exec()调用,捕获执行错误便于排查:

// 示例:amixer命令的错误处理
exec(`/usr/bin/amixer -D pulse sset Master ${volume}%`, (error, stdout, stderr) => {
  if (error) {
    console.error(`amixer执行失败: ${error.message}`);
    return;
  }
  if (stderr) {
    console.error(`amixer错误输出: ${stderr}`);
    return;
  }
});

// 示例:firefox命令的错误处理
exec(`/usr/bin/firefox ${PLAYER_CONTROL_ENDPOINT}`, (error, stdout, stderr) => {
  if (error) {
    console.error(`firefox启动失败: ${error.message}`);
    return;
  }
});

5. 重启服务生效

sudo systemctl daemon-reload
sudo systemctl restart speaker.service

内容的提问来源于stack exchange,提问作者DONGHAEY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 00:37:42