I have a script which creates a virtual machine and gives me back an IP address. Then I would like to do something like this:
waitforssh 192.168.2.38 && ssh 192.168.2.38
And it will wait for the machine to be up and ssh to be responding, then ssh into it.
waitforssh is the command I need to find.
Would nmap, netcat, fping or ping do the job? I tried netcat but it gives up in just a couple of seconds if the host is unreachable.
It needs to handle the fact that the machine itself is booting and might take some time to respond to network packets.
I don't have a host that I can ssh to and control whether it's up or not, but this should work:
Or a shell script that is more explicit:
Save it as (say)
waitforssh.sh
and then call it withsh waitforssh.sh 192.168.2.38
This is a 'ping_ssh' script I'm using. It handles timeout cases, fast success, and won't prompt for passwords or be fooled by the port being open but not responding as with 'nc' based solutions. This combines several answers found on various stackoverflow related sites.
Something simple like this does the job, waiting 5 seconds between attempts and discarding STDERR
The ssh command can be given a command to perform on the remote machine as the last paramater. So call
ssh $MACHINE echo
in a loop. On success it returns 0 in $?, on failure 255. You must of course use paswordless authentication with certificates.Well, I'm not sure what you mean by to be up, but what about:
First command
ping | ... | head -1
waits for server to sent single ping reply and exists. Then ssh comes into play. Be aware thatgrep
can buffer output, so this is what--line-buffered
is for.You can wrap this command with bash function to use it exactly the way you've described.
-o ConnectTimeout=2
is a slightly hacky way of getting around not responding to network packets, reportingssh: connect to host 10.10.0.3 port 22: Operation timed out
until it's responsive.Then, when the host responding to network packets, the 1 second sleep with happen in-between
ssh: connect to host 10.10.0.3 port 22: Connection refused
as we wait for ssh to come up.This uses
socat
to connect and wait for the server to say something, which will be the SSH version info:Adjust host, timeouts, and sleep interval as desired.
You might not need
-T2
, which sets a timeout for inactivity after the TCP connection is already established, but in my case I was connecting to a QEMU virtual machine, and QEMU opens forwarded ports before the virtual OS is genuinely listening. It's harmless, in any case.