Shell Scripting:检查互联网连接的正确方法?

Alo*_*oha 30 networking shell-script internet

我发现脚本说他们检查互联网连接。如果接口启动,一些检查IP地址但它不检查互联网连接。我发现一些像这样使用 ping:if [ 'ping google.com -c 4 | grep time' != "" ]; then但有时这可能不可靠,因为 ping 本身可能因某种原因挂起(例如,等待某些卡住的 IO)。

关于使用脚本检查互联网连接的正确/可靠方法的任何建议?我必须使用一些软件包吗?

cron例如,它需要能够定期检查,然后在连接断开时执行某些操作,例如调用ifup --force [interface]

Ada*_*atz 36

我强烈建议不要使用ping来确定连接性。由于担心源自其网络的ping 泛洪攻击,有太多网络管理员禁用ICMP(它使用的协议)。

相反,我在您可以预期打开的端口上使用可靠服务器的快速测试:

if nc -zw1 google.com 443; then
  echo "we have connectivity"
fi
Run Code Online (Sandbox Code Playgroud)

nc在其端口扫描模式下使用 netcat ( ) ,快速戳(-z零 I/O 模式 [用于扫描])具有快速超时(-w 1最多等待一秒钟,尽管 Apple OS X 用户可能需要使用-G 1) . 它在端口 443 (HTTPS) 上检查 Google。

我使用 HTTPS 而不是 HTTP 来努力防止可以在端口 80 (HTTP) 上为任何主机应答的强制门户透明代理。使用端口 443 时这种情况不太可能发生,因为会出现证书不匹配,但它仍然会发生。

如果您想证明这一点,您需要验证连接的安全性:

test=google.com
if nc -zw1 $test 443 && echo |openssl s_client -connect $test:443 2>&1 |awk '
  handshake && $1 == "Verification" { if ($2=="OK") exit; exit 1 }
  $1 $2 == "SSLhandshake" { handshake = 1 }'
then
  echo "we have connectivity"
fi
Run Code Online (Sandbox Code Playgroud)

这会检查连接(而不是等待 openssl 超时),然后进行 SSL 握手,在验证阶段键入。如果验证“OK”或退出时出现错误(“false”),它会静默退出(“true”),然后我们报告结果。

  • 我尊重吉利斯,但这是正确的答案。 (6认同)
  • 添加`-d`,例如`nc -dzw1`,这样它就不会侦听STDIN 并不确定地挂在脚本中。并且可能使用 8.8.8.8 而不是 google.com 来保存查找。`nc -dzw1 8.8.8.8 443` (3认同)
  • @dezza 有点晚了......但仅供参考,超时“不工作/脚本冻结”似乎是 nc 中的一个错误。请参阅此链接 /sf/answers/1881101561/ 超时在 macOS 10.13.4 中对我来说也不起作用,我必须使用 Homebrew 安装“gnu netcat 0.7.1”,才能解决此问题。 (2认同)

Gil*_*il' 34

测试 IPv4 连接

如果您的网络允许 ping,请尝试 ping 8.8.8.8(由 Google 运行的服务器)。

if ping -q -c 1 -W 1 8.8.8.8 >/dev/null; then
  echo "IPv4 is up"
else
  echo "IPv4 is down"
fi
Run Code Online (Sandbox Code Playgroud)

测试 IP 连接和 DNS

如果您只希望在 DNS 也正常工作时测试成功,请使用主机名。

if ping -q -c 1 -W 1 google.com >/dev/null; then
  echo "The network is up"
else
  echo "The network is down"
fi
Run Code Online (Sandbox Code Playgroud)

测试网络连接

某些防火墙会阻止 ping。有些地方有防火墙,可以阻止除通过 Web 代理以外的所有流量。如果要测试 Web 连接性,可以发出 HTTP 请求。

case "$(curl -s --max-time 2 -I http://google.com | sed 's/^[^ ]*  *\([0-9]\).*/\1/; 1q')" in
  [23]) echo "HTTP connectivity is up";;
  5) echo "The web proxy won't let us through";;
  *) echo "The network is down or very slow";;
esac
Run Code Online (Sandbox Code Playgroud)


Alo*_*oha 11

我制作了一个脚本,它使用多种方式来检查互联网连接(ping、nc 和 curl,感谢 Adam Katz、Gilles 和 Archemar)。我希望有人觉得这很有用。随意根据自己的喜好对其进行编辑/优化。

检查您的网关、DNS 和 Internet 连接(使用 curl、nc 和 ping)。把它放在一个文件中,然后让它可执行(通常sudo chmod +x filename

#!/bin/bash

GW=`/sbin/ip route | awk '/default/ { print $3 }'`
checkdns=`cat /etc/resolv.conf | awk '/nameserver/ {print $2}' | awk 'NR == 1 {print; exit}'`
checkdomain=google.com

#some functions

function portscan
{
  tput setaf 6; echo "Starting port scan of $checkdomain port 80"; tput sgr0;
  if nc -zw1 $checkdomain  80; then
    tput setaf 2; echo "Port scan good, $checkdomain port 80 available"; tput sgr0;
  else
    echo "Port scan of $checkdomain port 80 failed."
  fi
}

function pingnet
{
  #Google has the most reliable host name. Feel free to change it.
  tput setaf 6; echo "Pinging $checkdomain to check for internet connection." && echo; tput sgr0;
  ping $checkdomain -c 4

  if [ $? -eq 0 ]
    then
      tput setaf 2; echo && echo "$checkdomain pingable. Internet connection is most probably available."&& echo ; tput sgr0;
      #Insert any command you like here
    else
      echo && echo "Could not establish internet connection. Something may be wrong here." >&2
      #Insert any command you like here
#      exit 1
  fi
}

function pingdns
{
  #Grab first DNS server from /etc/resolv.conf
  tput setaf 6; echo "Pinging first DNS server in resolv.conf ($checkdns) to check name resolution" && echo; tput sgr0;
  ping $checkdns -c 4
    if [ $? -eq 0 ]
    then
      tput setaf 6; echo && echo "$checkdns pingable. Proceeding with domain check."; tput sgr0;
      #Insert any command you like here
    else
      echo && echo "Could not establish internet connection to DNS. Something may be wrong here." >&2
      #Insert any command you like here
#     exit 1
  fi
}

function httpreq
{
  tput setaf 6; echo && echo "Checking for HTTP Connectivity"; tput sgr0;
  case "$(curl -s --max-time 2 -I $checkdomain | sed 's/^[^ ]*  *\([0-9]\).*/\1/; 1q')" in
  [23]) tput setaf 2; echo "HTTP connectivity is up"; tput sgr0;;
  5) echo "The web proxy won't let us through";exit 1;;
  *)echo "Something is wrong with HTTP connections. Go check it."; exit 1;;
  esac
#  exit 0
}


#Ping gateway first to verify connectivity with LAN
tput setaf 6; echo "Pinging gateway ($GW) to check for LAN connectivity" && echo; tput sgr0;
if [ "$GW" = "" ]; then
    tput setaf 1;echo "There is no gateway. Probably disconnected..."; tput sgr0;
#    exit 1
fi

ping $GW -c 4

if [ $? -eq 0 ]
then
  tput setaf 6; echo && echo "LAN Gateway pingable. Proceeding with internet connectivity check."; tput sgr0;
  pingdns
  pingnet
  portscan
  httpreq
  exit 0
else
  echo && echo "Something is wrong with LAN (Gateway unreachable)"
  pingdns
  pingnet
  portscan
  httpreq

  #Insert any command you like here
#  exit 1
fi
Run Code Online (Sandbox Code Playgroud)


Arc*_*mar 3

there are many IPs on internet, a light approach is to ping some of them

 if ping -c 4 google.com ; then OK ; else KO ; fi
 if ping -c 4 facebook.com ; then OK ; else KO ; fi
 if ping -c 4 nsa.gov ; then OK ; else KO ; fi # <- this one might not reply
Run Code Online (Sandbox Code Playgroud)

a more complete answer might be getting pages using wget

 wget google.com -o google.txt
 if parse google.txt ; then OK ; else KO ; fi
Run Code Online (Sandbox Code Playgroud)

where

  • parse is a program you write that ensure google.txt is not a (too old) cached version of google.com