4

The ssh command does not run from inside a bash script, but it does run from the shell.

I created a simple script and it shows the ssh command fails before it reaches the remote machine.

The shell output shows the following:

  • The remote machine is up
  • The script is on localhost and the ssh command is in a function called doit
  • Executing the script returns error on line 5 (the line with the ssh command): "No such file or directory"
  • Copy and paste the ssh command to the shell, hit enter, it executes and reaches the remote machine, which returns and error because no key is setup (expected)

Output from the shell:

~ $ nping -c 1 104.248.173.32

Starting Nping 0.7.01 ( https://nmap.org/nping ) at 2019-04-23 22:04 ICT
libnsock mksock_bind_addr(): Bind to 0.0.0.0:0 failed (IOD #1): Invalid argument (22)
SENT (0.0016s) Starting TCP Handshake > 104.248.173.32:80
RECV (0.0017s) Handshake with 104.248.173.32:80 completed

Max rtt: 0.177ms | Min rtt: 0.177ms | Avg rtt: 0.177ms
TCP connection attempts: 1 | Successful connections: 1 | Failed: 0 (0.00%)
Nping done: 1 IP address pinged in 0.00 seconds
~ $ cat /tmp/test.sh
#!/usr/bin/env bash

function doit() {
  RUN="/usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 [email protected] hostname"
  "$RUN"
  echo "RESULT: $?"
}

doit  
~ $ /tmp/test.sh
/tmp/test.sh: line 5: /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 [email protected] hostname: No such file or directory
RESULT: 127
~ $ /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 [email protected] hostname
Host key verification failed.
~ $ echo $?
255

I expected the ssh command in the script to attempt to run hostname on the remote machine, and for the remote machine to error because no key is setup.

What actually happened is that the ssh command in the script didn't run because there was a "No such file or directory" error.

Why am I seing a "No such file or directory" error when the ssh command is run from the script, even though the script is there, ssh is there, and the remote machine is there?

5
  • Because you're trying to run a program named /usr/bin/ssh -o BatchMode... instead of /usr/bin/ssh with arguments -o BatchMode.... Is the RUN variable even necessary (I assume this snippet might have been extracted from a larger script where it's actually useful)? Commented Apr 23, 2019 at 15:46
  • Depending what it is you are connecting here to, you might want to consider removing the public IP ... Commented Apr 23, 2019 at 15:46
  • @cfillion I don't see what the difference is you are trying to highlight, doesn't the command execute in the same way from the variable? Yes you are correct it's been extracted from another script and the variable gets used later to print the command out Commented Apr 23, 2019 at 16:00
  • @cptPH Thanks, it's a test server that will be deleted later Commented Apr 23, 2019 at 16:01
  • 1
    See BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! Short summary: don't put commands in variables, they're for holding data, not code. Commented Apr 23, 2019 at 16:09

1 Answer 1

3
/usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 root@ipaddress hostname

and

"/usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 root@ipaddress hostname"

...are not the same. The former executes the command /usr/bin/ssh with the specified arguments. The latter treats the whole string, including the arguments, as the command name.

You did the former when running the command in the shell. However the doit function does the latter with "$RUN". You are getting "No such file or directory" because, indeed, there is no file named ssh -o BatchMode... (truncated for brevity) inside of /usr/bin.

Either execute the command directly if possible, or remove the quotes:

function doit1() {
  /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 root@ipaddress hostname
  echo "RESULT: $?"
}

function doit2() {
  # assuming there is some usefulness to using a variable in the actual script
  RUN="/usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=3 root@ipaddress hostname"
  $RUN
  echo "RESULT: $?"
}
Sign up to request clarification or add additional context in comments.

3 Comments

Please don't use or recommend eval -- it's a massive bug magnet.
That makes a lot of sense, I was confused for a few seconds because I've put commands in variables before and haven't had any issues, and now I realize it's because in those cases I didn't have double quotes around the variable so the command wasn't being exectued as a string. Using $RUN instead of "$RUN" and I get the expected result. Thanks
@vy218 That'll only work reliably if the command doesn't include any shell metacharacters (quotes, escapes, pipes, redirects, etc). Functions are really a better way to do this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.