如何使用 bash 测试 Internet 连接?

如何测试一个互联网连接,而不会连接到某个网站? 我是说,如果有联系但是网站关闭了怎么办?是否有一张与世界联系的支票?

288481 次浏览

我之前写过一些脚本,它们只是使用 telnet 连接到端口80,然后传输文本:

HTTP/1.0 GET /index.html

然后是两个 CR/LF 序列。

如果您获得了某种形式的 HTTP 响应,那么通常可以假定站点正在运行。

如果本地命名服务器关闭,

ping 4.2.2.1

是一个容易记住的总是在运行的 IP (它实际上是一个名称服务器,甚至)。

关闭默认网关:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error

Ping 就是被设计来做你想做的事情的。但是,如果站点阻塞 ICMP 回显,那么您总是可以执行 telnet 以将某些站点、 wget 或 curl 的80端口移植。

Pong 并不意味着服务器上的 Web 服务正在运行; 它只是意味着服务器正在响应 ICMP 回显。 我建议使用 curl 并检查它的返回值。

超级感谢用户 有些人的帖子在这里: https://bbs.archlinux.org/viewtopic.php?id=55485 on 2008-09-2002:09:48

查看/sys/class/net 应该是一种方法

下面是我的脚本,用于测试除了返回循环之外的网络连接。 我使用下面的另一个脚本,我有定期测试,如果我的网站是可访问的。如果它不能访问一个弹出窗口提醒我一个问题。

下面的脚本防止我每五分钟接收弹出消息每当我的笔记本电脑没有连接到网络。

#!/usr/bin/bash


# Test for network conection
for interface in $(ls /sys/class/net/ | grep -v lo);
do
if [[ $(cat /sys/class/net/$interface/carrier) = 1 ]]; then OnLine=1; fi
done
if ! [ $OnLine ]; then echo "Not Online" > /dev/stderr; exit; fi

对于那些新加入 bash 的人,请注意: 最后的“ if”语句测试 if NOT [ ! ]如果是这种情况,则在线和退出。有关更多详细信息,请参见 man bash 并搜索“ Expressions may be united”。

P.S. 我觉得 ping 不是最好的选择,因为它的目的是测试连接 一个特定的宿主 NOT,如果有任何类型的连接 一个网络

附注: 上面的内容可以在 Ubuntu 12.04上使用。/sys 可能不存在于其他发行版中,参见下文:

现代的 Linux 发行版包括一个/sys 目录作为虚拟档案系统(sysfs,类似于/proc,它是 procfs) ,它存储并允许修改连接到系统的设备,而许多传统的 UNIX 和类 UNIX 操作系统使用/sys 作为到内核源代码树的符号链接。[需要引证]

来自 Wikipedia https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

没有信号

#!/bin/bash


wget -q --spider http://google.com


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

- q : 沉默模式

Spider : 不要获取,只需检查页面可用性

$? : shell 返回码

0 : shell“ All OK”代码

没有 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

查看谷歌的索引页面是另一种方式:

#!/bin/bash


WGET="/usr/bin/wget"


$WGET -q --tries=20 --timeout=10 http://www.google.com -O /tmp/google.idx &> /dev/null
if [ ! -s /tmp/google.idx ]
then
echo "Not Connected..!"
else
echo "Connected..!"
fi

这对 MacOSX 和 Linux 都适用:

#!/bin/bash


ping -q -c1 google.com &>/dev/null && echo online || echo offline

@ Jesse 的回答类似,这个选项可能比使用 ping的任何解决方案都要快得多,也许比 @ Jesse 的回答稍微高效一些。

find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1' {} \; | grep -q '1'

说明:

此命令使用 find-exec/sys/class/net/中未命名为 *lo*的所有文件运行命令。这些应该是指向目录的链接,这些目录包含有关计算机上可用网络接口的信息。

正在运行的命令是一个 sh命令,用于检查这些目录中文件 carrier的内容。$interface/carrier的值有三层含义—— 引用:

似乎有三个州:

  • ./载体不可读(例如,当在网络管理器中禁用接口时)。
  • ./运营商包含“1”(当接口被激活并连接到 WiFi 网络时)
  • ./运营商包含“0”(当界面被激活,它没有连接到 WiFi 网络)

@ Jesse 的回答中没有考虑第一个选项:

# Note: $0 == $interface
cat "$0"/carrier 2>&1

cat被用来检查 carrier的内容,并将所有输出重定向到标准输出,即使因为文件不可读而导致失败。 如果 grep -q在这些文件中找到 "1",这意味着至少有一个接口连接。grep -q的退出码将是最终的退出码。

用法

例如,使用这个命令的退出状态,您可以使用它在您的 ~/.xprofile中启动一个 Gnubiff,只有在您有一个 Internet 连接的情况下。

online() {
find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1 > /dev/null | grep -q "1" && exit 0' {} \;
}
online && gnubiff --systemtray --noconfigure &

参考文献

这个 bash 脚本不断检查 Internet,并在 Internet 可用时发出哔哔声。

#!/bin/bash
play -n synth 0.3 sine 800 vol 0.75
while :
do
pingtime=$(ping -w 1 8.8.8.8 | grep ttl)
if [ "$pingtime" = "" ]
then
pingtimetwo=$(ping -w 1 www.google.com | grep ttl)
if [ "$pingtimetwo" = "" ]
then
clear ; echo 'Offline'
else
clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
fi
else
clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
fi
sleep 1
done

捷径: fping 4.2.2.1 = > “4.2.2.1 is alive”

我更喜欢这样,因为它比 ping更快,输出更少,缺点是你必须安装它。

你可以使用任何 公众人士而不是一个特定的网站。

fping -q google.com && echo "do something because you're connected!"

-q返回一个退出代码,所以我只是展示了一个运行你在线的东西的例子。

在 mac 上安装: brew install fping; 在 ubuntu 上安装: sudo apt-get install fping

请确保您的网络允许 TCP 流量进出,然后您可以得到您的公共面对 IP 与以下命令

curl ifconfig.co

执行以下命令来检查网站是否正常运行,以及 Web 服务器显示的状态消息:

curl -Is http://www.google.com | head -1 HTTP/1.1 200 OK

状态码“200 OK”表示请求成功并且可以访问网站。

最佳答案不适用于 MacOS,所以对于那些 Mac 上的用户,我已经成功地测试了这个:

GATEWAY=`route -n get default | grep gateway`
if [ -z "$GATEWAY" ]
then
echo error
else
ping -q -t 1 -c 1 `echo $GATEWAY | cut -d ':' -f 2` > /dev/null && echo ok || echo error
fi

在 MacOS High Sierra 10.12.6上测试

最佳答案忽略了一个事实,即你可以有一个完全稳定的连接到你的默认网关,但这并不自动意味着你实际上可以达到的东西在互联网上。OP 询问他/她如何能够测试与世界的联系。因此,我建议更改顶部的答案,将网关 IP 更改为已知的 IP (x.y.z.w) ,该 IP 位于局域网之外。

所以答案就是:

ping -q -w 1 -c 1 x.y.z.w > /dev/null && echo ok || echo error

还删除了命令取代 译自: 美国《科学》杂志网站(https://stackoverflow. com/a/4708569/9050928)的不受欢迎的反勾。

如果你只是想在执行某些代码之前确保你已经连接到了这个世界,你也可以使用:

if ping -q -w 1 -c 1 x.y.z.w > /dev/null; then
# more code
fi

如果您的目标是实际检查 互联网访问权限,那么对于这个问题的许多现有答案是有缺陷的。有几件事你应该注意:

  1. 你的计算机有可能连接到一个网络,而该网络没有互联网接入
  2. 一台服务器可能会瘫痪而整个互联网却无法访问
  3. 即使你没有互联网接入,一个被俘获的门户也有可能为任意的 URL 返回一个 HTTP 响应

考虑到这一点,我认为最好的策略是通过 HTTPS 连接联系 好几个站点,如果有任何这些站点响应,则返回 true。

例如:

connected_to_internet() {
test_urls="\
https://www.google.com/ \
https://www.microsoft.com/ \
https://www.cloudflare.com/ \
"


processes="0"
pids=""


for test_url in $test_urls; do
curl --silent --head "$test_url" > /dev/null &
pids="$pids $!"
processes=$(($processes + 1))
done


while [ $processes -gt 0 ]; do
for pid in $pids; do
if ! ps | grep "^[[:blank:]]*$pid[[:blank:]]" > /dev/null; then
# Process no longer running
processes=$(($processes - 1))
pids=$(echo "$pids" | sed --regexp-extended "s/(^| )$pid($| )/ /g")


if wait $pid; then
# Success! We have a connection to at least one public site, so the
# internet is up. Ignore other exit statuses.
kill -TERM $pids > /dev/null 2>&1 || true
wait $pids
return 0
fi
fi
done
# wait -n $pids # Better than sleep, but not supported on all systems
sleep 0.1
done


return 1
}

用法:

if connected_to_internet; then
echo "Connected to internet"
else
echo "No internet connection"
fi

关于这种方法的一些注意事项:

  1. 它可以有力地对抗我上面提到的所有错误的肯定和否定
  2. 所有请求都是并行发生的,以最大限度地提高速度
  3. 如果你的 严格来说有互联网接入,但是 DNS 没有功能,或者你的网络设置有问题,这将返回 false,我认为在大多数情况下这是一个合理的做法

在 Bash 中,通过 /dev/{ UDPTCP}使用它的网络包装器 /主持人/左舷:

if : >/dev/tcp/8.8.8.8/53; then
echo 'Internet available.'
else
echo 'Offline.'
fi

(:是 Bash no-op,因为您只想测试连接,而不想进行处理。)

为了获得最快的结果,定位 DNS 服务器:

ping -c1 "8.8.8.8" &>"/dev/null"


if [[ "${?}" -ne 0 ]]; then
echo "offline"
elif [[ "${#args[@]}" -eq 0 ]]; then
echo "online"
fi

可作为独立命令使用: 链接状态

如果你想处理俘虏门户,你可以这样写:

if [[ $(curl -s -D - http://www.gstatic.com/generate_204 2>/dev/null | head -1 | cut -d' ' -f 2) == "204" ]]; then
echo 'online'
else
echo 'offline'
fi

或者,如果你想要一些更易读的东西,可以区分囚禁门户和缺乏信号:

function is_online() {
# Test signal
local response
response=$(curl --silent --dump-header - http://www.gstatic.com/generate_204 2> /dev/null)
if (($? != 0)); then return 2; fi
# Test captive portal
local status=$(echo $response | head -1 | cut -d' ' -f 2)
((status == "204"))
}
is_online && echo online || echo offline