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

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

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

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

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

答案1

我强烈推荐反对用于ping确定连接性。有太多网络管理员禁用ICMP(它使用的协议)由于担心ping 洪水来自其网络的攻击。

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

if nc -zw1 google.com 443; then
  echo "we have connectivity"
fi

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 '
  $1 == "SSL" && $2 == "handshake" { handshake = 1 }
  handshake && $1 == "Verification:" { ok = $2; exit }
  END { exit ok != "OK" }'
then
  echo "we have connectivity"
fi

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

opensslawk代码逐行分析输出:

  1. 如果该行的第一个单词是“SSL”,第二个单词是“Verification”,则设置handshake1
  2. 如果handshake设置并且该行的第一个字是“验证”,
    则保存第二个字(验证状态)ok并停止读取
  3. 0如果验证状态为 ,则以 (true)值退出OK,否则以1(false) 值退出。
    我们!=在这里使用是因为 shell 退出代码是相反的

(awk 的一个奇怪之处:exit在读取行时运行只会停止读取行并进入END条件,从中您可以真正执行exit。)

答案2

测试 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

测试 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

测试网络连接

有些防火墙会阻止 ping。有些地方有防火墙,可以阻止除网络代理之外的所有流量。如果要测试 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

答案3

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

检查您的网关、DNS 和互联网连接(使用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

答案4

感谢每个用户和其他网站的贡献,我设法在 3 天内完成了这个脚本。我会让它免费使用。

当连接丢失时,此脚本会自动更新 IP 地址,并且会持续执行此操作。

#!/bin/bash

# Autor: John Llewelyn
# FB: fb.com/johnwilliam.llewelyn
# Twitter: twitter.com/JWLLEWELYN
# TLF: +584-1491-011-15
# Its use is free.
# Description: Connection Monitor for ADSL modem.
# Requirements:
# Copy this code or save to /home/administrator/ConnectionMonitor.sh
# It requires the installed packages fping beep and cron
# Comment the blacklist pcspkr snd-pcsp in /etc/modprobe.d/blacklist.conf
# Give execute permissions: chmod +x /home/administrator/ConnectionMonitor.sh
# Add this line in crontab -e with root user
# @reboot sleep 120 && /home/administrator/MonitorDeConexion.sh

#################################################################################
# SETTINGS
TEST="8.8.8.8"       # TEST PING
ADAPTER1="enp4s0"    # EXTERNAL ETHERNET ADAPTER

# Report
LOGFILE=/home/administrator/Documentos/ReportInternet.log

# Messages
MESSAGE1="Restoring Connectivity..."
MESSAGE2="Wait a moment please..."
MESSAGE3="No Internet connectivity."
MESSAGE4="Yes, there is Internet connectivity."
#################################################################################

# Time and Date
TODAY=$(date "+%r %d-%m-%Y")

# Show IP Public Address
IPv4ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet " |cut -d' ' -f6|cut -d/ -f1)
IPv6ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet6 " |cut -d' ' -f6|cut -d/ -f1)

# Alarm
alarm() {
    beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550$
}

# Restoring Connectivity
resolve() {
    clear
    echo "$MESSAGE1"
    sudo ifconfig $ADAPTER1 up;sudo dhclient -r $ADAPTER1;sleep 5;sudo dhclient $ADAPTER1
    echo "$MESSAGE2"
    sleep 120
}

# Execution of work
while true; do
    if [[ "$(fping -I $ADAPTER1 $TEST | grep 'unreachable' )" != "" ]]; then
        alarm
        clear
        echo "================================================================================" >> ${LOGFILE}
        echo "$MESSAGE3 - $TODAY"                                                               >> ${LOGFILE}
        echo "$MESSAGE3 - $TODAY"
        echo "================================================================================" >> ${LOGFILE}
        sleep 10
        resolve
    else
        clear
        echo "================================================================================"   >> ${LOGFILE}
        echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1" >> ${LOGFILE}
        echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1"
        echo "================================================================================"   >> ${LOGFILE}
        sleep 120
    fi
done

粘贴箱:https://pastebin.com/wfSkpgKA

相关内容