Shell脚本:检查Internet连接的正确方法?


26

我发现脚本说他们检查互联网连接。有些人会检查接口的IP地址,但不会检查Internet连接。我发现有些使用ping的方法是这样的:if [ 'ping google.com -c 4 | grep time' != "" ]; then但是有时候ping可能由于某些原因而挂起(例如,等待某些卡住的IO),因此这可能并不可靠。

关于使用脚本检查Internet连接的正确/可靠方式的任何建议?我需要使用一些软件包吗?

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

Answers:


29

测试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代理。如果要测试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

在使用ethtool进行任何OSI第3层检查之前,您可能需要合并对物理连接(OSI第1层)的验证。$ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
jas

你能解释一下添加此请的目的>/dev/null
胺Harbaoui

@AmineHarbaoui - >/dev/null重定向标准输出到/dev/null,该空设备,其中其配置,因为它不是在这种情况下期望的(所有我们关心的是命令的退出值)。而是从echo行中获取更多适用的输出。
亚当·卡兹

27

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

相反,我在可以打开的端口上对可靠服务器进行了快速测试:

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

这会nc在其端口扫描模式下使用netcat(),它-z是一种具有快速超时(最多等待一秒钟)的快速戳(是零I / O模式(用于扫描-w 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

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


5
我尊重Gillies,但这是正确的答案。
gwillie

3
也添加-d例如,nc -dzw1这样它就不会监听STDIN并在脚本中无限期地挂起。并可能使用8.8.8.8而不是google.com来保存查找。nc -dzw1 8.8.8.8 443
dezza

我不确定Google的DNS解析器在提供HTTPS服务方面的可靠性如何。google.com服务器对于HTTPS应该更可靠(除非您在中国,但是两者都可能被阻止)。我从不需要-d脚本,也许是因为从未使用过未使用的管道。那应该很安全。
亚当·卡兹

1
@dezza – -w 1在没有连接的情况下仍然需要花费一秒钟的时间,尽管也许您nc有某种晦涩的问题。如果您安装的是最新版本的nmap,则可以ncat --send-only --recv-only -w 334ms将故障时间减少到三分之一nc(我发现334ms是一个不错的等待时间)。
亚当·卡兹

1
@dezza –我不知道为什么在该系统的nmap的ncat和netcat(nc)上都发生这种情况。您的网络或BSD系统上可能会发生一些奇怪的事情。随意创建一个新的unix.stackexchange问​​题,并获得不仅仅是我对这个问题的关注。如果您这样做,请在此处在评论中将其链接,然后将此主题链接到您的新问题。
亚当·卡兹

9

我编写了一个脚本,该脚本使用多种方式检查Internet连接(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

不错!谢谢 !我们应该将网关$GW设置为什么?
CiprianTomoiagă17年

@CiprianTomoiaga不需要,/sbin/ip route | awk '/default/ { print $3 }'从(希望)主接口获取网关地址。如果需要,可以自己设置网关IP地址。
PNDA

谢谢你!不过我想念的是可以将Internet中断存储在txt文件中以及自动发送给我的ISP的电子邮件中的选项。
rhand '18 -10-2

2

互联网上有很多IP,一种简便的方法是ping其中一些

 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

一个更完整的答案可能是使用 wget

 wget google.com -o google.txt
 if parse google.txt ; then OK ; else KO ; fi

哪里

  • parse是您编写的程序,可确保google.txt不是google.com的(太旧)缓存版本

1

多亏了每个用户和其他网站的贡献,我设法在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

pastebin:https//pastebin.com/wfSkpgKA


什么可以使这个答案更好:(1)解释脚本的工作方式。(如果用户的网络接口除之外的其他名称eth0,则用户似乎必须编辑脚本,但未提及。)(2)使用英语。(3)将所有shell变量(例如"$HOST""$LINE1""$LOG")为双引号。(4)设置LINE2或不使用它。(我怀疑你有LINE1 /  LINE2混同inet4 /  inet6)...(续)
G-人说“恢复莫妮卡”

(续)…(5)说您正在显示当前时间时实际显示当前时间,而不是捕获脚本启动时的时间并在脚本的整个生命周期中显示它。(6)我认为还有别的东西,但是我现在看不到。
G-Man说'Resstate Monica''De​​c

它是西班牙语,因为它是我的语言,但我可以用英语更正它。$ HOST是要尝试的地址。$ LINE1是通过eth0适配器连接的Internet连接。$ LINE2是由eth1适配器连接的Internet连接,如果您有2条Internet线路,则建议将其禁用。日期,如果我确认自启动脚本以来它保持相同的时间和日期,则必须更正该问题。这个周末我纠正了这个问题。
John Llewelyn

好吧,G曼,我做了一些更改,我仍然需要更正日期并改进一些内容。
John Llewelyn
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.