树莓派Node.js服务自启动后音量下调功能失效问题求助
问题根因
- 核心原因是shell脚本调用使用相对路径,但不同启动方式下进程的工作目录不一致:
在终端手动执行node server.js时,终端的当前工作目录就是server.js存放的/home/pi/Desktop,exec('sh volumeup.sh')和exec('sh volumedown.sh')可以直接找到同目录下的两个脚本,功能正常。
通过.desktop文件配置开机自启动时,系统不会自动将工作目录切换到可执行文件所在路径,默认工作目录是pi用户的家目录/home/pi。出现音量加正常、音量减失效的现象,是因为调试过程中volumeup.sh在/home/pi目录下存在副本,而volumedown.sh仅存放在/home/pi/Desktop目录下,开机启动时进程找不到volumedown.sh,点击音量减自然没有任何反应。手动终止自启动进程、在Desktop目录下重启服务后,工作目录切换回脚本所在目录,两个脚本都能被正常寻址,功能就全部恢复。 - 代码存在隐性缺陷:POST接口处理完请求后没有返回任何HTTP响应,浏览器提交表单后会持续处于等待响应的加载状态,只是本地调试时未触发明显异常。
- 存在长期运行隐患:
.desktop自启动时加载的用户环境变量不完整,如果shell脚本里的音量控制命令(比如amixer)使用相对写法,后续可能出现命令找不到、无权限访问音频设备的问题。
修复方案
- 第一步:修改Node.js服务代码,使用绝对路径调用shell脚本,同时补全接口响应:
var express = require('express'); var path = require('path'); var open = require('open'); var fs = require('fs'); const { exec } = require('child_process'); var bodyParser = require('body-parser'); var port = 3000; var app = express(); // 提前定义脚本所在的绝对目录,即server.js所在目录 const SCRIPT_PATH = __dirname; app.get('/', function(req, res){ res.sendFile(path.join(__dirname, 'index.html')); }); app.use(bodyParser.urlencoded({ extended: false })); app.post('/', function(request, respond) { var inputValue = request.body.volume; if (inputValue == "up") { exec(`sh ${SCRIPT_PATH}/volumeup.sh`); } if(inputValue == "down") { exec(`sh ${SCRIPT_PATH}/volumedown.sh`); } // 补全响应,避免浏览器一直挂起 respond.sendStatus(200); }); app.listen(port, function(err){ if(err){ console.log(err); }else{ open('http://localhost:' + port); } }); - 第二步:修改
.desktop自启动配置,补全工作目录参数,修改后内容如下:[Desktop Entry] Encoding=UTF-8 Type=Application Name=NodeVolumeService Exec=/usr/bin/node /home/pi/Desktop/server.js # 指定启动时的工作目录为脚本所在目录 WorkingDirectory=/home/pi/Desktop StartupNotify=false Terminal=true Hidden=false - 第三步:检查两个shell脚本内容,将内部的音量控制命令替换为绝对路径。比如常用的
amixer命令,可以先在终端执行which amixer获取绝对路径(通常是/usr/bin/amixer),替换脚本里的amixer即可,避免开机时环境变量不全导致命令找不到。
内容的提问来源于stack exchange,提问作者foreverandthreedays
相关产品推荐
相关产品推荐

