如何创建一个bash脚本来检查SSH连接?

124

我正在创建一段bash脚本,用于登录远程机器并创建私钥和公钥。

我的问题是远程机器不太可靠,它们并不总是处于工作状态。我需要一个bash脚本来检查SSH连接是否正常运行,然后再为未来使用创建密钥。


3
通常,人们会在本地计算机上运行 ssh-keygen 命令生成密钥对,然后使用 ssh-copy-id 将公钥复制到远程计算机上。但是看起来您正在采用不同的方法。为什么?您的目标是什么? - ephemient
1
由于您显然正在更改远程机器建立连接的方式,请考虑部署 mosh。http://mosh.mit.edu/ 它旨在在不稳定的连接上补充SSH。我对它有非常好的体验。 - Daniel
@ephemient 我知道有点晚了,但很明显这个密钥不是为本地机器或本地用户而设计的。 - Abandoned Cart
14个回答

222
你可以通过ssh返回的返回值来检查这个。
$ ssh -q user@downhost exit
$ echo $?
255

$ ssh -q user@uphost exit
$ echo $?
0

编辑:另一种方法是使用nmap(您不需要拥有密钥或登录信息):
$ a=`nmap uphost -PN -p ssh | grep open`
$ b=`nmap downhost -PN -p ssh | grep open`

$ echo $a
22/tcp open ssh
$ echo $b
(empty string)

但是你需要使用grep命令来获取消息(nmap不使用返回值来显示端口是被过滤、关闭还是开放的)。
编辑2:
如果你对ssh端口的实际状态感兴趣,你可以将grep open替换为egrep 'open|closed|filtered'
$ nmap host -PN -p ssh | egrep 'open|closed|filtered'

只是为了完整起见。

2
请问在SSH中,哪个返回代码表示成功,哪个表示失败?为了完整起见,请指明一下。 - Henley
想知道如果SSH尝试就这样挂起会怎么样? - Sibbs Gambling
2
很好的回答!但是,您没有提到尝试使用 ssh 连接一个已关闭的主机会在超时(例如60秒)后才失败-这对某些用途可能是禁止的。此外,如果主机名在 ~/.ssh/config 中定义,则第一种 ssh 方法有效,而第二种 nmap 方法会失败并显示“无法解析“<主机名>””。 - ssc
3
关于命令的解释一点都没有……或者你实际在做什么……$?是什么? - Toskan
1
@ssc 您可以添加 -o 选项来限制超时时间。以下示例将其减少到 5 秒:ssh -o ConnectTimeout=5 -q user@downhost exit - grim_i_am
显示剩余5条评论

33
您可以使用类似以下的内容
$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

如果ssh连接正常,这将输出“ok”


1
如果需要密码且未正确输出“ok”,尽管远程可连接,此操作将失败。 - Matthaeus Gaius Caesar
很好的回答,但是您需要删除BatchMode选项,以便在需要密码的系统上运行。 - Luca Fagioli

23
ssh -q -o "BatchMode=yes" -i /home/sicmapp/.ssh/id_rsa <ID>@<Servername>.<domain> "echo 2>&1" && echo $host SSH_OK || echo $host SSH_NOK

2
一行输出:(ssh -q -o“BatchMode=yes”-o“ConnectTimeout=3”user@host.com“echo 2>&1”&& echo SSH_OK || echo SSH_NOK)| tail -n1 - Xdg

22

在补充@Adrià Cidre的回答时,您可以执行以下操作:

status=$(ssh -o BatchMode=yes -o ConnectTimeout=5 user@host echo ok 2>&1)

if [[ $status == ok ]] ; then
  echo auth ok, do something
elif [[ $status == "Permission denied"* ]] ; then
  echo no_auth
else
  echo other_error
fi

10

在成功连接时,以下ssh命令应该具有退出代码0,否则具有非零值。

ssh -q -o BatchMode=yes user@remote.com exit

if [ $? != "0" ]; then
    echo "Connection failed"
fi

2
太好了!我还建议添加 -o ConnectTimeout=5,以便在目标端口被过滤的情况下更快地退出。 - Daniel

7

尝试:

echo quit | telnet IP 22 2>/dev/null | grep Connected

1
这种方法的问题在于它无法识别 ssh_config 中定义的主机(即 /etc/ssh/config 或 ~/.ssh/config)。 - Ding-Yi Chen

4

继@user156676后,检查一系列IP地址:

#!/bin/sh
IP='192.168.0.'
PWD='your_password'
USR='your_usr'

for i in $(seq 229 255);do
    sshpass -p $PWD ssh -q -o ConnectTimeout=3 ${USR}@${IP}${i} exit
    let ret=$?
    if [ $ret -eq 5 ]; then
        echo $IP$i "Refused!"  $ret
    elif [ $ret -eq 255 ] ; then
        echo $IP$i "Server Down!" $ret
    elif [ $ret -eq 0 ] ; then
        echo $IP$i "Connnected!" $ret
    else
        echo $IP$i "Unknown return code!" $ret
    fi  
done

2

如果有人只想检查远程计算机的22号端口是否开放,可以使用这个简单的netcat命令。我使用它是因为nmap和telnet对我不可用。此外,我的ssh配置使用键盘密码验证。

这是GUESSWHOz提出的解决方案的一个变体。

nc -q 0 -w 1 "${remote_ip}" 22 < /dev/null &> /dev/null && echo "Port is reachable" || echo "Port is unreachable"

-q 0 的意思是空闲时立即离开。

-w 1 等待连接1秒钟。


1

连接到具有多个接口的服务器

ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.61;[ $? = 1 ] || ssh -o ConnectTimeout=1 -q Necktwi@192.168.1.51

0

我编写了这个脚本,用于检查服务器/etc/hosts中所有主机的netcat和SSH连接

逐行读取/etc/hosts文件,然后尝试使用netcat端口22进行连接,接着以“sshuttle”用户身份进行ssh连接

这是一种快速检查网络是否正常的方法

脚本使用“sshuttle”用户,这是一个在我所有主机上都具有公共/私有密钥并可以在任何地方进行ssh访问(非root用户)的帐户。我们使用此帐户来启动sshuttle VPN隧道,但您也可以添加任何具有对服务器的SSH访问权限的帐户

https://gist.github.com/perfecto25/8687d563716ba4923c77162be724beda

输出,

./conncheck.sh


netcat is installed, proceeding..
--------------------------------------
tm-us1 (127.0.0.1): ssh OK | nc OK
--------------------------------------
localhost (127.0.0.1): ssh OK | nc OK
--------------------------------------
atlas (192.168.142.21): ssh ERROR | nc OK
--------------------------------------
hydra (192.168.142.22): ssh OK | nc OK
--------------------------------------
nemesis (192.168.140.23): ssh OK | nc OK
--------------------------------------
vulcan (192.168.140.24): ssh OK | nc OK
--------------------------------------
athena (192.168.140.27): ssh OK | nc OK
--------------------------------------
nas1 (192.168.100.101): ssh ERROR | nc OK
--------------------------------------
tm-dev (192.10.23.71): ssh ERROR | nc ERROR
--------------------------------------
WARNING: Your password has expired.
Password change required but no TTY available.
infra01 (192.10.23.186): ssh ERROR | nc OK
--------------------------------------
ns-us1 (192.10.23.252): ssh ERROR | nc OK
--------------------------------------
ns-us2 (192.10.23.182): ssh ERROR | nc OK
--------------------------------------
proxy-us1 (192.10.23.120): ssh OK | nc OK
--------------------------------------
simtm-us1 (192.10.23.236): ssh OK | nc OK
--------------------------------------
tm-us1 (192.10.23.104): ssh OK | nc OK
--------------------------------------
tm-us2 (192.10.23.215): ssh OK | nc OK
--------------------------------------
tm-dev (192.10.23.77): ssh OK | nc OK
--------------------------------------
WARNING: Your password has expired.
Password change required but no TTY available.
tm-uat (192.10.23.225): ssh ERROR | nc OK
--------------------------------------
vpn-us1 (192.10.23.193): ssh OK | nc OK
--------------------------------------

请在您的回答中提供脚本,而不是(或除了)链接。 - izogfif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接