如何使用bash测试Internet连接?

142

如何在不ping网站的情况下测试网络连接?我的意思是,如果网站宕机了,但是有连接怎么办?有没有检查与世界连接的方法?


2
ping几个不同的网站? - anon
1
但我不想ping网站,还有其他选项吗? - lauriys
6
我只是想看看是否还有其他的方法! - lauriys
2
没有比向一组地址发送和接收单个数据包更好的方法,这些地址您知道不会同时离线。另一种方法是检查您当前设置的DNS,如果您不希望应用程序ping一个更公共的域名。 - Tamara Wijsman
@Neil:我不知道提问者的原因,但有些地方会屏蔽ping。例如,在我的工作场所,我无法ping到子网外的任何东西。 - PTBNL
14
我想知道是否有人在听,而不发出任何声音! - Kaz
22个回答

174

没有ping

#!/bin/bash

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

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

-q:静默模式

--spider:只检查页面是否可用,不获取文件

$?:Shell返回代码

0:Shell“全部正常”代码

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

4
非常好...但前提是假定该盒子有Wget。嵌入式设备等可能没有。;) - Eric Sebasta
6
尝试这个命令: echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1该命令将发送一个HTTP GET请求到Google网站,并将响应输出重定向到/dev/null文件,任何错误信息也将被重定向到/dev/null。 - user3439968
1
tcping 在这里也会有帮助。( tcping www.yahoo.com 80 ) && echo "网站已经上线" - David Ramirez
2
@user3439968 你需要给 nc 增加超时时间来确保它能够超时。可以使用类似 nc google.com 80 -w 10 的命令。 - kaptan
2
可以使用纯Bash解决。https://dev59.com/MnNA5IYBdhLWcg3wgeSk#56138210 - Luchostein
显示剩余3条评论

101

ping您的默认网关:

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

14
良好的技巧可以修改为用于函数:“function ping_gw() { ... && return 0 || return 1 }”,然后可以按如下方式使用:“ping_gw || (echo“无网络,再见”&& exit 1)” - memnoch_proxy
1
在Mac OS上,通过复制粘贴无法工作: “-bash:ip:命令未找到 ping:非法选项--w” - Benedikt S. Vogler
1
如果在虚拟化客户机上运行而主机未连接,则会发出误报。 - admirabilis
1
在 elementary os(0.4.1,Acer Aspire E 15)上给我假阴性。 - Malcolm
2
小心处理这个问题。我刚刚通过执行“ifconfig down wlan0”进行了测试,尽管我实际上无法访问外部世界,但我仍然有一个默认网关并且可以ping通。 - Bruno Bronosky
显示剩余9条评论

32

这适用于MacOSX和Linux两个操作系统:

#!/bin/bash

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

除了OSX(ping:invalid option -- w)之外。 - avishayp
fping google.com或者简单地fping 8.8.8.8可以神奇地完成任务,而且你还能获得状态码,无需测试它("google.com is alive")。 - Roger
@avishayp 如果你改变超时参数,使用“-t”而不是“-w”,它可以在macOS的ping版本上工作 -ping -q -t 1 -c 1 google.com &> /dev/null && echo online || echo offline - sidneys
@sidneys 我刚在Ubuntu上尝试了你的版本,但不行。我也测试了当前发布的版本,在MacOSX上也不行。如果我去掉-w1,那么两个平台上都可以正常工作,所以我选择这个。 - legel
OP说,不需要对可能已经宕机或被屏蔽的特定网站进行ping操作。 - Alex

32

非常感谢用户somedrew在此处发布的帖子:https://bbs.archlinux.org/viewtopic.php?id=55485,时间为2008年9月20日02: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”语句测试是否没有[!]联网,如果是这种情况则退出。请参阅man bash并搜索“表达式可组合”以获取更多详细信息。

P.S. 我觉得ping不是在这里使用的最好工具,因为它旨在测试与特定主机的连接,而不是测试是否存在任何类型的网络连接。

P.P.S. 上述内容适用于Ubuntu 12.04,/sys可能不存在于其他某些发行版中。请参见下面:

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

来自维基百科https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard


1
小心!“cat /sys/class/net/wwan0/carrier”在Ubuntu 14.04 LTS上无法工作。 - dotnetCarpenter
1
你可能想在 cat /sys/class/net/$interface/carrier 后面加上 2>/dev/null,以防网络被禁用时出现错误输出。 - jarno

25
在Bash中,可以通过其网络包装器使用/dev/{udp,tcp}/host/port
if : >/dev/tcp/8.8.8.8/53; then
  echo 'Internet available.'
else
  echo 'Offline.'
fi

(:是Bash中的无操作指令,因为您只想测试连接,而不做任何处理。)

(译注:这里的“无操作指令”指的是一个没有实际操作的占位符,通常用于在脚本中占位或注释代码。)


1
我认为这是最便携和简单的答案了? - cmyui
1
当连接丢失时,它有时会卡住。 - polendina
@polendina 或许加上超时时间?timeout 10 true >/dev/tcp/8.8.8.8/53?(将“:`”改为“true”) - Luchostein
1
timeout 10 true >/dev/tcp/8.8.8.8/53 对我仍然被阻止,但将整个命令包装在 sh 中,在超时的情况下我们想要杀死它,这样可以解决问题:timeout 10 sh -c "true >/dev/tcp/8.8.8.8/53"。这样一来,也可以使用 : 替代 true - agostonbarna
只是用ping命令就能更快地完成,不需要那么多的封装。 - undefined

8

最佳答案没有考虑到您可能与默认网关有着完全稳定的连接,但这并不意味着您一定能够实际访问互联网上的某些内容。OP询问如何测试与外界的连接。因此,我建议将顶部答案中的网关IP更改为已知的位于LAN之外的IP(x.y.z.w)。

因此,答案将变为:

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

同时移除不受欢迎的反引号用于命令替换[1].

如果你只是想在执行某些代码之前确保已连接到互联网,你也可以使用以下方法:

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

7

确保您的网络允许 TCP 流量进出,然后可以使用以下命令获取公共 IP 地址:

curl ifconfig.co

7

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

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

状态代码“200 OK”表示请求成功,网站可达。


2
一个更好的实现方式可能是 `curl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "在线"; else; echo "离线"; fi;` - Luca Galasso

6

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

HTTP/1.0 GET /index.html

接着两个CR/LF序列。

如果你收到了HTTP响应的任何形式,通常可以假定该网站正在运行。


3
为什么要重新发明轮子呢?curl和wget都已经完美地做到了这一点。 - Adam Rosenfield
7
因为wget和curl并非总是可用的(例如,在公司环境中受到限制),Telnet自Unix诞生以来就一直是标准组件。 - paxdiablo
是的,Telnet已经是相当长一段时间用于测试连接的标准方式了。 - PTBNL
2
不错的观点,虽然wget相当常见。另一个选择是netcat(nc),但在这种情况下,它并没有比telnet更好。 - Adam Rosenfield

5

最受欢迎的答案对于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上进行测试。


2
route 命令更改为 route -n get default 2> /dev/null | grep gateway,以避免在离线时向 stderr 写入错误。 - devstuff

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