如何使用bash测试Internet连接?


113

在不ping通某些网站的情况下如何测试互联网连接?我的意思是,如果有连接但站点已关闭怎么办?是否可以检查与世界的联系?


2
ping几个不同的站点?

1
但我不想ping网站,没有其他选择吗?
lauriys

6
我只想看看也许还有其他方法!
lauriys

2
没有比将单个数据包发送和接收到一组您不会立即全部脱机的地址更好的方法,另一种方法是检查当前设置的DNS(如果您不希望应用程序ping更公开的地址)域。
塔玛拉·威斯曼

14
我想知道是否有人在听而没有发出声音!
卡兹(Kaz)2012年

Answers:


130

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

2
非常好...但是当然要假设盒子有wget。嵌入式设备,可能不会。;)
Eric Sebasta

5
试试这个:echo -e“ GET google.com HTTP / 1.0 \ n \ n” | nc google.com 80> / dev / null 2>&1
user3439968

1
tcping在这里也有帮助。(tcping www.yahoo.com 80)&&回声“ Site is up”
David Ramirez,

如果在这里使用if / else语句,说明会很棒。谢谢 !
Danijel-James W

1
@ user3439968您需要添加超时以nc确保超时。像nc google.com 80 -w 10
kaptan '17

93

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 "no network, bye" && exit 1)
memnoch_proxy 2013年

1
在Mac OS上,通过复制粘贴无法正常工作:“ -bash:ip:找不到命令ping:非法选项-w”
Benedikt S. Vogler,2016年

1
如果在未连接主机的情况下从虚拟化来宾运行,则会发出错误警报。
Teresa e Junior

1
给我基本操作系统(0.4.1,Acer Aspire E 15)的误报
马尔科姆(Malcolm

1
请注意这一点。我只是通过这样做进行了测试,ifconfig down wlan0并且我仍然具有默认网关,并且可以ping通,即使实际上我无法访问外界。
布鲁诺·布鲁诺斯基

29

超级感谢用户somedrew在这里发布的帖子:https://bbs.archlinux.org/viewtopic.php?id = 55485于2008-09-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'语句在线测试NOT [!],如果不是,则退出。请参阅man bash并搜索“表达式可以合并”以了解更多详细信息。

PS:我觉得ping并不是在这里使用的最佳方法,因为它的目的是测试与特定主机的连接,而不是测试是否与任何类型的网络都有连接。

PPS以上内容可在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
你可以把它放到2>/dev/null以后cat /sys/class/net/$interface/carrier的情况下,网络已禁用于没有错误输出。
jarno

25

这适用于MacOSX和Linux:

#!/bin/bash

ping -q -w1 -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)

9

在Bash中,通过/ dev / { udptcp } / host / port使用它的网络包装:

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

:是Bash禁止操作,因为您只想测试连接,但不进行处理。)


7

在此之前,我已经编写了脚本,只需使用telnet连接到端口80,然后传输文本即可:

HTTP/1.0 GET /index.html

随后是两个CR / LF序列。

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


3
为什么要重新发明轮子?curl和wget都完美地做到了这一点。
亚当·罗森菲尔德

6
因为wget和curl并不总是可用(例如,公司环境中的限制)。从时间t = 0开始,Telnet已成为每个UNIX的标准部分。
paxdiablo,2009年

是的,很长时间以来,远程登录一直是测试连接的一种非常标准的方法。
PTBNL,

2
好点,尽管wget很普遍。另一个选择是netcat(nc),尽管在这种情况下,它与telnet相比没有任何改进。
亚当·罗森菲尔德2009年

7

最重要的答案是,您可以与默认网关建立完全稳定的连接,但这并不意味着您实际上可以在Internet上访问某些东西。OP询问他/她如何测试与世界的联系。因此,我建议通过将网关IP更改为LAN之外的已知IP(xyzw)来更改最佳答案。

因此答案将变为:

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

6

确保您的网络允许TCP流量进出,那么您可以使用以下命令获取面向公众的IP

curl ifconfig.co

5

执行以下命令以检查网站是否已启动以及该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 "Online"; else; echo "Offline"; fi;
Luca Galasso,

4

如果您的本地名称服务器已关闭,

ping 4.2.2.1

是一个易于记忆的永远使用的IP(甚至实际上是一个名称服务器)。


5
ping 8.8.8.8(Google NS)
2014年

4

顶部投票答案因此对于那些在Mac上,我已经成功地测试了这并不适用于MacOS的工作:

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 '18

4

此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

3

最短的方法:fping 4.2.2.1=>“ 4.2.2.1还活着”

我喜欢它,因为它比更快,更详细的输出ping,缺点是您必须安装它。

您可以使用任何公共DNS,而不是特定的网站。

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

-q 返回退出代码,因此我仅显示一个运行您在线的示例。

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


2

Ping的设计完全可以满足您的需求。但是,如果该站点阻止了ICMP回显,那么您始终可以将telnet连接到某个站点,wget或curl的端口80。


2

检查Google的索引页是另一种方法:

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

2

@Jesse的答案类似,此选项可能比使用@Jesse的答案的任何解决方案都快得多,ping并且效率可能稍高。

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

解释:

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

正在运行的sh命令是检查carrier那些目录中文件内容的命令。的值$interface/carrier具有3个含义- 引用

似乎有三种状态:

  • ./carrier不可读(例如,在网络管理器中禁用接口时)。
  • ./carrier包含“ 1”(激活接口并将其连接到WiFi网络时)
  • ./carrier包含“ 0”(当接口被激活并且未连接到WiFi网络时)

@Jesse的答案未考虑第一个选项。sh条带化的命令是:

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

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

用法

例如,使用此命令的退出状态,你可以用它启动gnubiff~/.xprofile只有当你有互联网连接。

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 &

参考


1

Pong并不意味着服务器上的Web服务正在运行。它仅表示服务器正在回复ICMP回显。我建议使用curl并检查其返回值。


0

如果您的目标是实际检查Internet访问,则该问题的许多现有答案都是有缺陷的。您应该注意的几件事:

  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 ,我认为这在大多数情况下是合理的做法

curl的返回码未经过测试。在我的系统上,如果网络不可用,curl会给出rc = 6(DNS解析失败),但是此代码仍然报告“ Connected to internet”。
ceperman

@ceperman curl的返回代码在其指示的行上进行测试if wait $pid;。不知道为什么这在您的系统上不起作用。确定要使用bash吗?
Ajedi32 '19

@ceperman另一种可能性;也许顶部列表中的一个URL 确实为您返回了成功,即使其他URL的名称解析失败?
Ajedi32 '19

2
我的bash非常基础,因此我继续阅读wait,现在了解了返回代码确实正在测试中。我重新复制了您的代码,今天它可以工作了-糟糕!上次我一定搞砸了,尽管我不明白是什么或如何。尽管如此,Mea culpa。道歉。
ceperman '19


-1

这明显比此处发布的任何解决方案都要,并且可以用于测试特定主机

诀窍是使用比以下人员少用的DNS解析器来解决IP ping

validateConnection () {
    host="${1}"
    ip=$(getent ahostsv4 "${host}" | awk '{ print $1 }' | head -n1)
    ping -c1 "${ip}" 2>&1 >"/dev/null"

    if [ "${?}" -ne 0 ]; then
        echo "No connection to: ${host}" >&2
        exit 1
    fi
}

2
尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。- 评分
大卫·巴克

它不适用于这种特殊情况。
Alberto Salvia Novella
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.