4

In terminal if I login with ssh and run a command like service something reload it runs just fine, but when I execute the same command in a nodejs script with the ssh2 library (.exec function) it doesn't run and i get an error "ash: command not found".

Tried with sudo service.. but it's same thing.

Some commands do work tho, like uptime or ifconfig, but service doesn't and I need that one. The server to which I am connecting is a router that runs open wrt.


this is the nodejs script:

const Client = require('ssh2').Client;
const conn = new Client();

conn.on('ready', async() => {

  conn.exec('service network reload', {
    env: {'PATH': '/usr/sbin:/usr/bin:/sbin:/bin'},
  }, (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'
});

A screenshot of the terminal output for which:

wtf

Alex
  • 66,732
  • 177
  • 439
  • 641
  • Checkout [Connecting to remote SSH server (via Node.js/html5 console)](https://stackoverflow.com/questions/38689707/connecting-to-remote-ssh-server-via-node-js-html5-console) – Muhammed Sidan Sep 19 '20 at 11:41
  • 2
    I would imagine your nodejs/ssh2 setup is using a different environment than your login terminal. Can you do things like `printenv` and check the results? Is there an init file? – h0r53 Sep 21 '20 at 13:46
  • If you can pass an `options` object with your .exec(), what happens with `opts.shell` set to the full pathname for your chosen shell? – Milag Sep 21 '20 at 17:23
  • `ash: printenv: not found` if I exec this command with ssh2 :( – Alex Sep 24 '20 at 15:11
  • Milag there doesn't seem to be a `shell` option for ssh2 exec. There is a `shell` method but I think it starts a interactive terminal, which I do not want. I just need to execute a single command and quit – Alex Sep 24 '20 at 15:13

3 Answers3

1

You get "bash command not found error." because your PATH does not include the location of the service executable.

Compare result of echo $PATH; from ssh2 with your terminal. if your ssh2 miss some paths update your environment.

Fatih Şennik
  • 1,295
  • 5
  • 12
  • it's not bash, it's ash. I tried settings the path but same thing happens – Alex Sep 24 '20 at 15:09
  • also running `echo $path` from the ssh2 doesn't work. it just stalls and I have to press ctrl-c to force quit – Alex Sep 24 '20 at 15:09
1

You have to pass an options object that includes the key env whose value is itself an object of key value pairs.

exec('sudo service something reload', {env: {'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:'}}, function (error, stdout, stderr) 
{
    console.log(stdout, stderr, error);
});
Ron
  • 5,900
  • 2
  • 20
  • 30
  • Oh, you are not on `bash`. Instead of copy/pasting, try to use the pointers and adjust to your specific environment, like try installing sudo... – Ron Sep 24 '20 at 15:25
  • but it should be installed if I can do stuff within a macos terminal ssh session. Could the issue be in the ssh2 node library? – Alex Sep 24 '20 at 17:02
  • I do not think so, I think the issue is with your PATH, that is why `sudo` can not be seen .. so any debugging that you can enable is a plus to figuring out what is wrong. – Ron Sep 24 '20 at 17:04
1

If you're getting a command not found error, it simply means your command, in this case service, is not found within the environment's $PATH.

Either, set your environment properly for your connection, or use absolute paths for the commands.

For systemd service, use /usr/sbin/service something reload, or /bin/systemctl reload something etc.

You can find paths of your executables with which command, like which service or which systemctl.

For older init script services, run /etc/init.d/something restart.

ΔO 'delta zero'
  • 3,506
  • 1
  • 19
  • 31
  • interesting. I ran `which command` in terminal and it shows nothing for `sudo` or `service`, but shows binary path for `ifconfig`. So basically it shows nothing for the commands that work in terminal and not in nodejs, and shows the path for commands that work in both terminal and nodejs – Alex Sep 24 '20 at 17:15
  • Try running `which service` in the terminal where it works :-) – ΔO 'delta zero' Sep 24 '20 at 17:16
  • I did and it shows nothing. I think these commands don't have binaries in open wrt? But I don't understand why do they work in terminal, and not in a ssh2 session – Alex Sep 24 '20 at 17:18
  • I don't have much experience with OpenWRT, but this sounds weird at least... It's possible they're only aliases for other executables, like systemctl. Try `which systemctl` – ΔO 'delta zero' Sep 24 '20 at 17:20
  • same thing, shows nothing. I think I have no other choice but to start a terminal session with ssh2 and somehow autotype the commands :( – Alex Sep 24 '20 at 17:23
  • @Alex which user are you running your commands with, try running `whoami` or `id` and share the output – Ron Sep 24 '20 at 17:24
  • Does your OpenWRT use systemd at all? Maybe it uses old init.d scripts... in that case, try sth like `/etc/init.d/yourservice reload` – ΔO 'delta zero' Sep 24 '20 at 17:25
  • Yep that works, thanks! But the 2nd argument is `restart`, and apparently the command does not want to finish in ssh2 for some reason (I have to press ctrl-c), but I can live with that :s – Alex Sep 24 '20 at 17:31
  • Glad to hear that :-) What is it that hangs? The remote command, or your node script? I think your code keeps the connection alive after the exec, try closing the conn when the command closes – ΔO 'delta zero' Sep 24 '20 at 17:34
  • I did it finally with ifup, ifdown commands. those are in sbin and work normally. – Alex Sep 24 '20 at 19:36