为探测远程SSH端口的Bash命令添加超时功能遇报错求助
/dev/tcp Let's sort out this timeout problem with your SSH port detection command. The core issue here is that timeout is designed to run external executable commands by default, but (: </dev/tcp/$vm_ip/22) is a shell compound construct (a subshell with redirection), not a standalone binary. That's why your two attempts hit errors—here's how to fix it:
Working Solution 1: Wrap the Shell Command in bash -c
Since your port check relies on shell-specific behavior (the special /dev/tcp file), you need to tell timeout to run a shell instance that can parse this logic. Use bash -c to pass your command as a string to bash:
timeout --preserve-status 5 bash -c "(: </dev/tcp/$vm_ip/22) &>/dev/null"
You can even simplify it by dropping the unnecessary subshell (the parentheses don't add anything here):
timeout --preserve-status 5 bash -c "</dev/tcp/$vm_ip/22 &>/dev/null"
Why Your Previous Attempts Failed
- Storing the command in a variable: When you run
timeout --preserve-status 5 $SSH_CMD, the shell splits the variable into separate arguments.timeouttries to run(:as a command, which doesn't exist—hence the "No such file or directory" error. - Directly using parentheses with
timeout:timeoutexpects a command name as its first argument after options. The(is a shell syntax token, not a command, so the shell throws a syntax error when it encounters it unexpectedly.
Working Solution 2: Use nc (Netcat) for Simpler Port Checks
If your system has netcat installed, this is a more straightforward alternative that plays nicely with timeout without needing shell trickery:
timeout --preserve-status 5 nc -z $vm_ip 22 &>/dev/null
The -z flag tells nc to just probe the port without establishing a full connection, which is exactly what you need for a quick check.
内容的提问来源于stack exchange,提问作者Howard Shane

