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

Posted

技术标签:

【中文标题】如何在 Linux 上使用 Bash 脚本检查 Internet 访问?【英文标题】:How can I check Internet access using a Bash script on Linux? 【发布时间】:2013-06-21 21:21:36 【问题描述】:

在我的学校,网络不可用(每天晚上 23:00 之后学校会断网,让我们睡觉>..ping -w1 ...。

也就是说,当我使用:ping -q -w1 -c1 8.8.8.8 来检查 Internet 连接是否启动/关闭时,它将在那里没有任何输出并且不会退出,就像我使用单个 cat 一样。

我不知道为什么会这样,但我认为问题与 school-internet-service 有关。有什么建议吗? (我认为wget 可能是一个不错的选择,但我该如何使用呢?)

【问题讨论】:

这可以帮助***.com/questions/929368/… 【参考方案1】:

使用 wget:

#!/bin/bash

wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
        echo "Online"
else
        echo "Offline"
fi

【讨论】:

效果很好。非常感谢!我的旧版本缺少--tries,因此无法使用。 就个人而言,我通过创建wget -q --tries=10 --timeout=20 -O - http://google.com > /dev/null 来增强此模式。这会丢弃输出,这意味着文件不会被遗弃,写入权限也不会出现任何问题。 你真的应该使用--spider 选项,因为它会发送一个http HEAD 请求,而不是一个http GET 请求。现在,在这种情况下,您正在检查 google.com,这是一个非常轻量级的页面,因此它可能没问题。但作为一般规则,如果您只是想检查某些内容是否可用而不实际下载,则应使用HEAD 请求。我已相应地添加到答案中。【参考方案2】:

如果学校真的关闭了他们的路由器,而不是将所有流量重定向到“你为什么不睡觉”页面,则无需下载整个网页或发送 HTTP 标头。您所要做的就是建立连接并检查是否有人在听。

nc -z 8.8.8.8 53

这将输出“连接到 8.8.8.8 端口 53 [tcp/domain] 成功!”如果有人在听,则返回值 0。

如果你想在 shell 脚本中使用它:

nc -z 8.8.8.8 53  >/dev/null 2>&1
online=$?
if [ $online -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi

【讨论】:

这是最快的方法,它 ping dns 服务器而不是获取 google 的网站数据。竖起大拇指。 在这里使用超时可能会很好 nc -z -w 5 8.8.8.8 53 >/dev/null 2>&1【参考方案3】:

用途:

#!/bin/bash

INTERNET_STATUS="UNKNOWN"
TIMESTAMP=`date +%s`
while [ 1 ]
 do
    ping -c 1 -W 0.7 8.8.4.4 > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
        if [ "$INTERNET_STATUS" != "UP" ]; then
            echo "UP   `date +%Y-%m-%dT%H:%M:%S%Z` $((`date +%s`-$TIMESTAMP))";
            INTERNET_STATUS="UP"
        fi
    else
        if [ "$INTERNET_STATUS" = "UP" ]; then
            echo "DOWN `date +%Y-%m-%dT%H:%M:%S%Z` $((`date +%s`-$TIMESTAMP))";
            INTERNET_STATUS="DOWN"
        fi
    fi
    sleep 1
 done;

输出将产生如下内容:

./internet_check.sh

UP   2016-05-10T23:23:06BST 4
DOWN 2016-05-10T23:23:25BST 19
UP   2016-05-10T23:23:32BST 7

行尾的数字表示前一个状态的持续时间,即向上 19 秒,向下 7 秒。

【讨论】:

欢迎来到 Stack Overflow!虽然这段代码可能会回答这个问题,但最好包含一些上下文,解释它的如何工作以及何时使用它。从长远来看,纯代码的答案没有用处。 在几分钟内经历了很多起伏。虽然 DropBox 在线并且可以上网...请参阅 unix.stackexchange.com/a/190610/19694,他们提到 nc 比使用 ping 更好,因为很多主机商也禁用了 ICMP。 我看不到如何使用上面的代码获得持续时间。我试过了,每行的“持续时间”单调增长。 TIMESTAMP 不是每次循环都要重置吗?【参考方案4】:

使用超时选项-t

ping -q -t 5 -w1 -c1 8.8.8.8 t

【讨论】:

这个解决方案的一个问题是,一些网络可能会阻止传出的 ping(我的大学有这样做的著名记录)。不过,OP 似乎并非如此。 @umlaeute,在这种情况下,您可以使用wget http://google.com 甚至(更好更简单)curl【参考方案5】:

没有 wget

#!/bin/bash

echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi

享受;)

【讨论】:

【参考方案6】:

安装 fping:> 问题比 ping 少。

fping google.com | grep alive

使用,例如,像:

#!/bin/bash

itest=$(fping google.com | grep alive)

while [ "$itest" == "" ]
        do
        sleep 5
        itest=$(fping google.com | grep alive)
done
echo now online

【讨论】:

fping 需要在运行示例之前安装。【参考方案7】:

使用上面的示例。我写了这个脚本来记录你的连接状态: https://gist.github.com/cganterh/ffc2fffa8263857cbece

首先,将以下代码保存到name.sh 文件中。

#!/bin/bash

while true
do
    wget -q --tries=10 --timeout=20 -O - http://google.com > /dev/null
    if [[ $? -eq 0 ]]; then
        echo $(date) "1" | tee -a log.csv
    else
        echo $(date) "0" | tee -a log.csv
    fi
    sleep 5
done

然后,在终端执行name.sh文件,然后查看同一文件夹log.csv的日志状态信息。

【讨论】:

【参考方案8】:

我决定将之前的几个答案结合起来,这样我以后就可以创建一个显示起起落落及其持续时间的图:

#!/bin/bash
#
# pinger is a bash shell script that monitors the network
# status every 15 seconds and records if it is up '1' or down '0'
# into the file log.csv from whence it may be plotted.
#
# author: J. W. Wooten, Ph.D.
# since: 11/12/2019
# version: 1.0
#
TIMESTAMP=`date +%s`
while [ 1 ]
  do
    nc -z -w 5 8.8.8.8 53  >/dev/null 2>&1
online=$?
    TIME=`date +%s`
    if [ $online -eq 0 ]; then
      echo "`date +%Y-%m-%d_%H:%M:%S_%Z` 1 $(($TIME-$TIMESTAMP))" | tee -a log.csv
    else
      echo "`date +%Y-%m-%d_%H:%M:%S_%Z` 0 $(($TIME-$TIMESTAMP))" | tee -a log.csv
    fi
    TIMESTAMP=$TIME
    sleep 15
  done;

这将每 15 秒输出到一个 CSV 文件。使用 Excel 或 Numbers,您可以读取文件并创建一个图表,该图表将显示 Internet 连接何时不可用以及持续时间。如果它从您的睡眠间隔发生变化,那么它正在花费时间尝试连接。我希望添加在下一次检测到网络关闭时向我发送文本的功能。

【讨论】:

【参考方案9】:

Majal's solution 的一个变体只是为了测试 ping 的返回代码,如果站点响应,则返回 0,如果没有回复,则返回 1,如果网络不可达,则返回 2。

    ping -c 1 -t 5 8.8.8.8 2&>1
    rc=$?
    [[ $rc -eq 0 ]] &&  echo "Connected to the Internet" ; exit 0 ;  \
 || [[ $rc -eq 1 ]] &&  echo "No reply from Google DNS" ; exit 1 ;  \
 || [[ $rc -eq 2 ]] &&  echo "Network unreachable" ; exit 2 ; 

使用ping的好处是不需要下载任何东西,提高了测试速度。

【讨论】:

【参考方案10】:

可靠的旧 ping 在单独的 Bash 脚本中:

#!/bin/bash
ipaddr='8.8.8.8' # Google's public DNS server
[[ -z `ping -c1 $ipaddr |& grep -o 'Network is unreachable'` ]] || exit 1
[[ -z `ping -c3 $ipaddr |& grep -o '100% packet loss'` ]] && exit 0 || exit 1

把它放在一个单独的脚本中。它将处理不同的网络情况,例如 (1) 未连接到网络,(2) 已连接到网络,但无法访问 Internet(或至少 Google),以及 (3) 连接到互联网。


您可以稍后使用脚本的exit code 来检查连接性,例如

~$ script-name && echo online || echo offline

【讨论】:

以上是关于如何在 Linux 上使用 Bash 脚本检查 Internet 访问?的主要内容,如果未能解决你的问题,请参考以下文章

Bash脚本:如何在Linux Shell上输出和格式化文本

我只想检查在Linux bash上的命令输出中列出的服务器上的网络接口状态

如何在 bash 脚本中使用正则表达式?

在 Linux 和 BSD 中使用和不使用 shebang 执行 Bash 脚本

如何在不运行Bash脚本的情况下语法检查?

如何在 bash 脚本中使用 find 命令检查目录大小