Issue
I am going to use the below bash script to ping a remote host's SSH port, which runs correctly:
(: </dev/tcp/$vm_ip/22) &>/dev/null
Now in some hosts, this command will take very long time (for example 3 minutes) to report failure as the host is down.
I am going to add timeout support for this command and make it return quickly (for example, return in 5 seconds) if the host is not responding.
SSH_CMD="(: </dev/tcp/$vm_ip/22) &>/dev/null"
timeout --preserve-status 5 $SSH_CMD
However, the above will output an error:
timeout: failed to run command ‘(:’: No such file or directory
Can you help me on how to fix this?
==EDIT 1==================
Tried to change the code like this (without defining the variable):
timeout --preserve-status 2 (: </dev/tcp/$vm_ip/22) &>/dev/null
The failure is:
./test.sh: line 45: syntax error near unexpected token `('
./test.sh: line 45: ` timeout --preserve-status 2 (: </dev/tcp/$vm_ip/22) &>/dev/null'
Solution
The parenthesis in your command are shell syntax for a subshell, but timeout
doesn't run the command it starts through a shell. Instead, it runs it directly. It sees (:
as the command name and tries to run it, which leads to an error since you're not likely to have such a command in the PATH
.
You'll need to add an explicit shell there, with something like this:
timeout --preserve-status 5 bash -c "(: </dev/tcp/$vm_ip/22) &>/dev/null"
Your second command line gives a syntax error because (
and )
are special tokens in the shell. That command line would also apply the redirections to timeout
itself, so the network connection would be opened before timeout
is even started.
You could quote the words there, i.e. timeout ... "(:"
etc, but that would only give the same result as timeout ... $SSH_CMD
.
I'm not exactly sure you need the subshell in there anyway, but you still need to run a shell under timeout
to have the redirections processed while the timeout is running.
Answered By - ilkkachu Answer Checked By - Marie Seifert (WPSolving Admin)