2

I'm working on a Bash script that makes an SSH connection via git at a given point during the script's actions. I'm trying to gracefully handle some errors that can occur, stopping the script before it ends up failing part of the way through.

At one point it runs a command like git push which initiates a push over SSH. There's a chance that this will connect to a new host for the first time, which leads to an interactive prompt verifying the validity of the host.

RSA key fingerprint is 96:a9:23:5c:cc:d1:0a:d4:70:22:93:e9:9e:1e:74:2f.
Are you sure you want to continue connecting (yes/no)? yes

I'm looking for ideas on how to either avoid the SSH prompt or fail the script early if the SSH host hasn't been approved by the user before.

I took a look at this question. The argument could be made that this question is a duplicate of that, but the solutions listed there don't apply to my situation. I'd prefer to detect that the SSH connection can't be made without the prompt and fail in that case.

2
  • Can you elaborate on why the solution you linked to doesn't apply to you? It seems like StrictHostKeyChecking=no is exactly what you want. You could try redirecting stdin to git eg git pull < /dev/null
    – jordanm
    Mar 20, 2017 at 4:55
  • No, I can't elaborate because I was wrong. :) I just didn't make the connection the first time I read through it. ilkkachu's answer made it clear to me. Feel free to mark duplicate. Mar 20, 2017 at 14:23

2 Answers 2

3

So, instead of adding the host to known_hosts automatically, you want to fail the connection if it doesn't already exist there. StrictHostKeyChecking is still the option to do this (as in the linked question), but instead of setting it to no, set it to yes. This will cause the connection to fail if the host key isn't known.

$ ssh -oStrictHostKeyChecking=yes me@somehost.somewhere
No ECDSA host key is known for somehost.somewhere and you have requested strict checking.
Host key verification failed.

ssh exits with status 255 if an error happens, including this case, so you can test for that in the script with something like

if [ "$?" = 255 ] ; then
    echo "there was an error"
fi

Of course it could be some other error too, you'd need to check the output from ssh to make sure.

2
  • This is a great solution. Thank you for the insight. I ended up being even more direct and just checked for the host as a known hosting using ssh-keygen -F hostname.com and running an exit conditionally on the result of that command. Mar 20, 2017 at 17:20
  • @RyanBurnette, that would be a quite straightforward solution, too.
    – ilkkachu
    Mar 20, 2017 at 18:12
0

The OpenSSH client may prompt the user either through the terminal or through the X11 display. If you want to make sure that the user won't be prompted, arrange to run the client with no controlling terminal and no X display. Getting rid of the X display is easy: unset the DISPLAY environment variable or set it to an empty string. To run the process with no controlling terminal, run it in a separate session. There's no POSIX utility for that but Linux has a setsid utility.

DISPLAY= setsid ssh …

Note that running the SSH client in its own session also runs it in its own process group. The main practical consequence of using setsid is that if the script is executed from an interactive shell, Ctrl+C won't kill the SSH client; you should put a trap for SIGINT in your script that kills the SSH client.

ssh_pid=
trap INT TERM 'if [ -n "$ssh_pid" ]; then kill "$ssh_pid"; fi'
DISPLAY= setsid ssh … &
wait "$ssh_pid"
unset ssh_pid

Beware that ssh returns the status code 0 if it can't make the connection because the host key verification failed. You'll need to rely on something else to determine whether the command succeeded.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .