SSH命令终端正常,Node.js ssh2库执行报“ash: command not found”
解决OpenWrt下ssh2.exec执行
service命令报"command not found"的问题 这个问题我在调试OpenWrt路由器的远程管理脚本时碰到过,核心原因很明确:
OpenWrt中的service不是系统内置命令,而是一个存放在/sbin/service的shell脚本。当你通过交互式SSH终端登录时,shell会自动加载/etc/profile或相关配置文件,把/sbin加入到PATH环境变量中;但ssh2的.exec方法默认启动的是非交互式、非登录shell,不会加载这些环境配置,哪怕你手动在env参数里指定PATH,有时候也会因为shell的执行逻辑问题不生效。而uptime、ifconfig这类命令之所以能正常运行,是因为它们通常位于/usr/bin或/bin目录下,这些路径在非交互式shell的默认PATH里。
下面给你几个可靠的解决方案:
方案1:直接使用service的绝对路径执行
这是最直接的解决方式,跳过PATH的问题,直接指定脚本的完整路径:
const Client = require('ssh2').Client; const conn = new Client(); conn.on('ready', async() => { // 使用绝对路径调用service脚本 conn.exec('/sbin/service network reload', (err, stream) => { if(err) return console.log(err); stream.on('close', () => console.log('ok')); stream.stderr.on('data', data => console.log(data.toString())); }); }).connect({ host: ROUTER_HOST, port: 22, username: 'root', password: '1234' });
方案2:显式调用登录shell执行命令
通过ash -l -c(OpenWrt默认shell是ash)启动登录shell,让它加载完整的环境变量配置,这样就能正常识别service命令:
const Client = require('ssh2').Client; const conn = new Client(); conn.on('ready', async() => { // 用登录shell执行命令 conn.exec('ash -l -c "service network reload"', (err, stream) => { if(err) return console.log(err); stream.on('close', () => console.log('ok')); stream.stderr.on('data', data => console.log(data.toString())); }); }).connect({ host: ROUTER_HOST, port: 22, username: 'root', password: '1234' });
方案3:验证并修正环境变量设置
如果你坚持要通过设置env参数解决,可以先执行echo $PATH命令查看非交互式shell的实际PATH:
conn.exec('echo $PATH', (err, stream) => { stream.on('data', data => console.log('当前PATH:', data.toString())); });
对比你设置的/usr/sbin:/usr/bin:/sbin:/bin,如果不一致,可能是ssh2的env参数没有正确覆盖,这时候可以尝试把命令改成export PATH=/usr/sbin:/usr/bin:/sbin:/bin && service network reload,强制在执行命令前设置PATH。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

