【问题标题】:Shell script to check whether a server is reachable?Shell脚本检查服务器是否可达?
【发布时间】:2012-01-20 06:40:00
【问题描述】:

我有 5 台 Solaris 服务器分布在不同的位置。 有时,由于各种原因(网络问题或服务器本身突然停机),从我所在的位置无法访问其中一些服务器。

所以我想编写一个 Bash shell 脚本来检查它们是否可以访问。我试过的是:

ssh ipaddress "uname -a"

设置了无密码身份验证。如果我没有得到任何输出,我将生成一封邮件。

  1. 还有其他方法可以检查服务器的可达性吗?
  2. 哪种方法最好?
  3. 我的尝试是否正确?

【问题讨论】:

  • 您可能想查看 Nagios。为您提供更多信息,并且可以尽可能详细。
  • 你的命令很好,但是当它失败时,有很多事情可能是错误的。从这个开始,但随着时间的推移添加更多检查以诊断个别问题。 ping 不会告诉您 ssh 守护程序是否启动,但相反,失败的 ssh 不会告诉您守护程序是否已死或服务器的电源适配器是否出现故障。

标签: bash shell solaris-10


【解决方案1】:

您可以做的最简单的检查可能是使用netcat 来检查打开的端口。

要检查 SSH(端口 22)的可达性,您可以这样做

if nc -z $server 22 2>/dev/null; then
    echo "$server ✓"
else
    echo "$server ✗"
fi

来自手册页:

-z   指定 nc 应该只扫描监听守护进程,而不向它们发送任何数据。

【讨论】:

  • 这正是我想要的。我不确定为什么人们宁愿使用发送包的 ping 来检查服务器是否可以访问。
  • 我的答案是近 3 年的最新答案,但我希望随着时间的推移会有更多人找到它!
  • 我建议在脚本中使用 -w 作为超时。否则 nc 在某些情况下可能会永远挂起。
  • 在我的 macOS 系统上,nc -z $server 在服务器无法访问时无限期挂起,添加-w 2 没有任何区别。我认为 -w 标志用于使已建立的连接到期,并且不影响 -z 标志。因此,使用 nc 检测无法访问的服务器似乎没有帮助——因为它只会挂起一分钟左右——我想要几秒钟后会放弃的东西。
  • 编辑之前的评论:在我的 macOS 系统上,nc -z $server 443 在服务器无法访问时无限期挂起,添加-w 2 没有任何区别。那是内置的nc。我使用 Mac Ports 安装 gnetcat ...如果服务器无法访问,'gnetcat -z -w 2 $server 443' 会在 2 秒后超时。
【解决方案2】:

您的 ssh 命令将测试的不仅仅是服务器是否可访问 - 要使其工作,ssh 服务器必须正在运行,并且一切都必须通过身份验证正确。

要查看服务器是否已启动,只需简单 ping 一下如何?

ping -c1 -W1 $ip_addr && echo 'server is up' || echo 'server is down'

【讨论】:

  • solaris 10 和我拥有的 bash shell,但它没有任何替代方案 非法选项 -w 它说
  • @gcbenison 您的 ping 还将测试更多内容,而不是服务器是否可访问。你可以像我的回答中详述的那样使用 netcat
【解决方案3】:

您可以使用 ping 手册页中的这些选项:

  • 只发送一个数据包(“c1”),
  • 安静模式(“q”),
  • (可选)等待 1 秒等待响应(“W1”)

    ping -c1 -W1 -q $server

Ping 根据错误类型返回不同的退出代码。 所以,要测试它是否有效,只需执行“echo $?”获取退出代码。 像这样:

ping 256.256.256.256 ; echo $?
# 68

ping -c 1 127.0.0.1 ; echo $?
# 0

ping -c 1 192.168.1.5 ; echo $?
# 2

在哪里

0 means host reachable
>0 means unreachable

因此,要在 bash 脚本中对此进行测试,您可以执行以下操作:

ping -c1 -W1 -q $server &>/dev/null
status=$( echo $? )
if [[ $status == 0 ]] ; then
     #Connection success!
else
     #Connection failure
fi

【讨论】:

    【解决方案4】:

    更多思考:使用 nmap 或 nc,永远不要 ping。

    Ping:为什么不应该使用 ping ? (1) 最好同时检查系统和端口。 (2) Ping 不可靠,因为 icmp echo 在很多情况下都被阻塞了。

    Nmap:这非常快,非常可靠,但需要安装 nmap 首选方法 NMAP(前主机 ip 127.0.0.1):

    nmap 127.0.0.1 -PN -p ssh | grep open
    

    Nc: nc 通常已安装,但是在某些系统(例如 Mac OS X)上,该命令会在无法访问的系统上挂起。 (见解决方法)

    nc -v -z -w 3 127.0.0.1 22 &> /dev/null && echo "Online" || echo "Offline"
    

    Mac OSX 解决方法:

    bash -c '(sleep 3; kill $$) & exec nc -z 127.0.0.1 22' &> /dev/null
    echo $?
    0
    bash -c '(sleep 3; kill $$) & exec nc -z 1.2.3.4 22' &> /dev/null
    echo $?
    143
    

    (示例说明通过一个好的和坏的主机连接到端口 22 的 ssh 示例,使用 $? 来确定它是否到达休眠时间为 3 秒的主机)

    对于 Mac 用户(主要)等,您可以像这样在脚本中使用命令:

        # -- use NMAP, if not avail. go with nc --
        if command -v nmap | grep -iq nmap ; then
            nmap ${ip} -PN -p ${ssh_port} | grep -iq "open"
            res=$?
        elif command -v nc | grep -iq nc ; then
            # -- run command if fails to complete in 3 secs assume host unreachable --
            ( nc -z ${ip} ${ssh_port} ) & pid=$!
            ( sleep 3 && kill -HUP $pid ) 2>/dev/null & watcher=$!
            if wait $pid 2>/dev/null; then
                pkill -HUP -P $watcher
                wait $watcher
                # -- command finished (we have connection) --
                res=0
            else
                # -- command failed (no connection) --
                res=1
            fi
        else
            echo "Error: You must have NC or NMAP installed"
        fi
    
        if [[ ${res} -lt 1 ]] ;then
            success=1
            echo "testing  => $ip SUCCESS connection over port ${ssh_port}"
            break;
        else
            echo "testing => $ip FAILED connection over port ${ssh_port}"
        fi
    

    【讨论】:

    • 感谢您的回答,非常有用。如果在公司代理后面,您知道如何使用 nc 命令吗?我如何通过代理滚刀连接到服务器?
    • 我只是检查了一下,对我来说,nmapssh 与服务器的连接要慢。那么,为什么像 &>/dev/null ssh user@ip true && echo "up" || echo "down" 这样实际上更接近 OP 的想法是错误的呢?
    【解决方案5】:

    您可以使用ping -c4 $ip_address,其中$ip_address 是远程服务器的IP,并解析输出以捕获成功的数据包和/或失败的数据包,并使用mail -s 通过电子邮件发送日志。

    这里有一些东西可以帮助您入门,您可以在此基础上再接再厉。

    ping -c4 www.google.com | awk '/---/,0'
    

    这将给出这样的输出 -

    [jaypal:~/Temp] ping -c4 www.google.com | awk '/---/,0'
    --- www.l.google.com ping statistics ---
    4 packets transmitted, 4 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 36.638/36.870/37.159/0.196 ms
    

    我检查了 Solaris man-page 中的 ping。 Solaris 机器上ping 的输出不同。此外,在 Linux 上,您可以通过声明 -c 和数据包数量来限制数据包。在 Solaris 上,您必须这样做 -

    ping -s www.google.com 2 4
    
    /usr/sbin/ping -s [-l | -U] [-adlLnrRv] [-A addr_family]
    [-c traffic_class] [-g gateway [ -g gateway...]] [-
    F flow_label] [-I interval] [-i interface] [-P tos] [-
    p port] [-t ttl] host [data_size] [npackets]
                               ^           ^
                               |           |
    ---------------------------------------  
    

    很遗憾,我没有方便的 solaris 盒子来帮助您。

    【讨论】:

    • 我得到 没有来自 ipaddr 的答复,因为我可以成功连接 SSH。
    • ping 的统计数据是什么?是100% packet loss吗?
    • 如果你只给了ping 而没有-c 选项,那么它将永远运行。您必须在 -c 选项中传递一个数字,以便它可以运行该时间并将输出传递给 awk 进行解析。
    • 没有 -C 选项我得到相同的消息
    • 看起来/etc/defaultroute 上的默认路由尚未设置。这指向处理流量的路由器。
    【解决方案6】:

    您可以将nc -z -G 2 SERVER_HOST PORT 方法与G 一起使用,而不是WG 用于在连接建立之前超时,所以如果主机不可达,你会更快地知道

    【讨论】:

    • 这可行,但我的 nc 版本不支持 -G 是 -w 和 -z。我用[[ $(nc -w 2 $HOST $PORT) ]] && echo $HOST reachable || echo $HOST unreachable这个用于bash
    【解决方案7】:

    你可以使用下面的命令,

    ping -c1 -W1 ip_addr || echo 'server is down'  
    

    您不能使用 $ip_addr,因为它会删除您的 IP 的第一个数字。

    【讨论】:

    • 更准确:ping -c1 -W1 ip_addr || echo 'Firewall somewhere in between here and the server I need to contact is dropping ping packets so I do not know if the server is up or not'
    猜你喜欢
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    相关资源
    最近更新 更多