如何在不 ping 某些网站的情况下测试 Internet 连接?我的意思是,如果有连接但站点已关闭怎么办?是否有检查与世界的联系?
20 回答
没有 ping
#!/bin/bash
wget -q --spider http://google.com
if [ $? -eq 0 ]; then
echo "Online"
else
echo "Offline"
fi
-q:静音模式
--spider : 不知道,只是检查页面可用性
美元?: 外壳返回码
0:外壳“一切正常”代码
没有 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
ping 默认网关:
#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error
超级感谢用户 somedrew在这里发帖:https ://bbs.archlinux.org/viewtopic.php?id= 55485 on 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' 语句测试是否在线 [!] 并在这种情况下退出。有关更多详细信息,请参阅 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
这适用于 MacOSX 和 Linux:
#!/bin/bash
ping -q -c1 google.com &>/dev/null && echo online || echo offline
在 Bash 中,通过/dev/ { udp , tcp } / host / port使用它的网络包装器:
if : >/dev/tcp/8.8.8.8/53; then
echo 'Internet available.'
else
echo 'Offline.'
fi
(:
是 Bash 无操作,因为您只想测试连接,而不是处理。)
最佳答案忽略了这样一个事实,即您可以与默认网关建立完美稳定的连接,但这并不意味着您实际上可以在互联网上访问某些内容。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
我之前写过脚本,只需使用 telnet 连接到端口 80,然后传输文本:
HTTP/1.0 GET /index.html
其次是两个 CR/LF 序列。
如果您得到某种形式的 HTTP 响应,您通常可以假设该站点正在运行。
执行以下命令检查网站是否已启动,以及 Web 服务器显示的状态消息:
curl -Is http://www.google.com | head -1 HTTP/1.1 200 OK
状态码“200 OK”表示请求已成功并且可以访问网站。
确保您的网络允许 TCP 流量进出,然后您可以使用以下命令取回面向公众的 IP
curl ifconfig.co
投票最多的答案不适用于 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 上测试
如果您的本地名称服务器已关闭,
平 4.2.2.1
是一个易于记忆的永远在线 IP(它实际上是一个名称服务器,甚至)。
此 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 还活着”
我更喜欢这个,因为它的输出速度更快,输出更简洁ping
,缺点是你必须安装它。
您可以使用任何公共 dns而不是特定网站。
fping -q google.com && echo "do something because you're connected!"
-q
返回一个退出代码,所以我只是展示了一个运行你在线的东西的例子。
在 mac 上安装:brew install fping
; 在 ubuntu 上:sudo apt-get install fping
Ping 旨在完成您想要做的事情。但是,如果站点阻止了 ICMP 回显,那么您始终可以远程登录到某个站点的 80 端口、wget 或 curl。
检查 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
与@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
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 &
参考
Pong 并不意味着服务器上的 Web 服务正在运行;它仅仅意味着服务器正在回复 ICMP 回显。我建议使用 curl 并检查它的返回值。
如果您的目标是实际检查Internet访问,那么该问题的许多现有答案都是有缺陷的。您应该注意的几件事:
- 您的计算机可能连接到网络而该网络没有互联网访问权限
- 如果整个互联网都无法访问,服务器可能会关闭
- 即使您没有 Internet 访问权限,强制门户也有可能返回任意 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
关于这种方法的一些注意事项:
- 它对我上面概述的所有误报和否定都很有效
- 所有请求都是并行发生的,以最大限度地提高速度
- 如果您在技术上可以访问互联网,但 DNS 无法正常工作,或者您的网络设置混乱,它将返回 false ,我认为在大多数情况下这是合理的做法
为了获得最快的结果,ping DNS 服务器:
ping -c1 "8.8.8.8" &>"/dev/null"
if [[ "${?}" -ne 0 ]]; then
echo "offline"
elif [[ "${#args[@]}" -eq 0 ]]; then
echo "online"
fi
可作为独立命令使用:linkStatus
如果你想处理强制门户,你可以这样做:
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