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

Posted

技术标签:

【中文标题】如何创建一个 bash 脚本来检查 SSH 连接?【英文标题】:How to create a bash script to check the SSH connection? 【发布时间】:2010-11-27 04:19:20 【问题描述】:

我正在创建一个 bash 脚本,该脚本将登录到远程机器并创建私钥和公钥。

我的问题是远程机器不是很可靠,而且它们并不总是启动。我需要一个 bash 脚本来检查 SSH 连接是否已启动。在实际创建密钥以供将来使用之前。

【问题讨论】:

通常,运行ssh-keygen 在本地机器上生成密钥对,然后运行ssh-copy-id 将公钥复制到远程机器。看来你做事的方式不同。为什么,你的目标是什么? 由于您显然要更改远程计算机建立连接的方式,因此请考虑部署 mosh。 mosh.mit.edu 旨在补充不稳定连接上的 SSH。我有很好的经验。 @ephemient 我知道这有点晚了,但它们的关键是 not 用于本地机器或 not 用于本地机器似乎很简单用户。 【参考方案1】:

你可以用 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'

只是为了完整。

【讨论】:

为了完整,你能指出哪个返回码代表成功,哪个代表SSH失败? 想知道如果 SSH 尝试只是挂在那里怎么办? 很好的答案!但是,您没有提到尝试 ssh 进入停机主机仅在例如超时后才会失败。 60 秒 - 这对于某些用途来说可能是令人望而却步的。此外,如果在~/.ssh/config 中定义主机名,则第一个ssh 方法有效,而第二个nmap 方法失败并显示Failed to resolve "<hostname>" 对命令完全没有解释......或者你实际上在做什么......什么是$??等 @ssc 您可以添加 -o 选项来限制超时持续时间。以下示例将其缩短为 5 秒:ssh -o ConnectTimeout=5 -q user@downhost exit【参考方案2】:

你可以使用这样的东西

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

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

【讨论】:

如果需要密码并且错误地输出不正确,这将失败,尽管远程是可连接的。 好答案但是您应该删除BatchMode 选项,以使其即使在需要密码的系统上也能正常工作。【参考方案3】:
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

【讨论】:

一行输出:(ssh -q -o "BatchMode=yes" -o "ConnectTimeout=3" user@host.com "echo 2>&1" && echo SSH_OK || echo SSH_NOK) |尾 -n1【参考方案4】:

补充@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

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

太棒了!我还建议添加 -o ConnectTimeout=5,以便在目标端口被过滤的情况下更快地退出。【参考方案6】:

试试:

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

【讨论】:

这种方法的一个问题是它无法识别 ssh_config 中定义的主机(即 /etc/ssh/config 或 ~/.ssh/config)【参考方案7】:

按照@user156676,检查ips范围:

#!/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

【讨论】:

【参考方案8】:

万一有人只想检查远程机器上的端口 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"

【讨论】:

【参考方案9】:

如果您想检查远程文件夹是否存在,或者是否真的要检查任何其他文件:

if [ -n "$(ssh "$user@$server" [ -d "$folder" ] && echo 1; exit)" ]; then
    # exists
else
    # doesn't exist
fi

不要忘记"$(ssh ...)" 中的引号。

【讨论】:

这没有回答问题。 OP 想要检查是否可以建立 SSH 连接,而不是检查远程 ssh 位置中的文件。【参考方案10】:

使用多个接口连接到服务器

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

【讨论】:

【参考方案11】:

使用 BASH 4+ 脚本的示例:

# -- ip/host and res which is result of nmap (note must have nmap installed)
ip="192.168.0.1"
res=$(nmap $ip -PN -p ssh | grep open)

# -- if result contains open, we can reach ssh else assume failure) --
if [[ "$res" =~ "open" ]] ;then
    echo "It's Open! Let's SSH to it.."
else
    echo "The host $ip is not accessible!"
fi

【讨论】:

【参考方案12】:

https://onpyth.blogspot.com/2019/08/check-ping-connectivity-to-multiple-host.html

以上链接是创建用于检查连接性的 Python 脚本。 您可以使用类似的方法并使用:

ping -w 1 -c 1 "IP Address" 

创建 bash 脚本的命令。

【讨论】:

这只会ping远程IP。不保证 ssh 连接是否可行。 感谢您指出,这里是 ssh xlinu.blogspot.com/2019/09/… export user="username" export pass="password" export i="hostname" export SSHPASS=$pass sshpass -e ssh $ 的代码user@$i -q "echo $i 是可访问的"【参考方案13】:

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

逐行读取/etc/hosts,然后尝试netcat 22端口,然后ssh作为“sshuttle”用户

检查网络健全性的快速方法

脚本使用“sshuttle”用户,这是一个在我的所有主机上都有 pub/priv 密钥的帐户,并且可以在任何地方进行 ssh(非 root 帐户),我们使用此帐户来启动 sshuttle *** 隧道,但您可以添加任何对服务器具有 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
--------------------------------------
***-us1 (192.10.23.193): ssh OK | nc OK
--------------------------------------

【讨论】:

【参考方案14】:

我觉得你在这里试图解决错误的问题。您不应该尝试使 ssh 守护进程更稳定吗?尝试运行monit 之类的东西,它将检查守护程序是否正在运行,如果没有运行则重新启动它(让您有时间找到 sshd 关闭您背后的根本问题)。还是网络服务麻烦?尝试查看man ifup。整个该死的事情只是想关闭你吗?好吧,这是一个更大的问题...尝试查看您的日志(从 syslog 开始)以查找导致您的 boxen 关闭的硬件故障或服务(可能是温度监视器?)。

使您的脚本具有容错性非常好,但您可能还希望使您的 boxen 具有容错性。

【讨论】:

Sam:有有效的用例让脚本检查它。例如(像我一样):我有一个 cron 作业在我的机器上运行,通过 rsync 将我的数据备份到我家的 nas。现在我在外面,甚至经常断开连接,如果连接不可用,我需要重新安排。我的boxen运行得很好,但俗话说:它总是电缆(a.k.a network)

以上是关于如何创建一个 bash 脚本来检查 SSH 连接?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 bash 脚本将 ssh 密钥添加到主机

用于检查连接的串行端口的Bash脚本

用于设置临时 SSH 隧道的 Bash 脚本

如何在 Linux 上使用 Bash 脚本检查 Internet 访问?

如何在 ssh / 远程 bash 命令中转义单引号字符?

如何在tmux窗口中启动脚本后自动终止ssh连接?