Shell Scripting: modo corretto per verificare la connettività Internet?


26

Ho trovato degli script che dicono che verificano la connettività Internet. Alcuni controllano l'indirizzo IP se l'interfaccia è attiva MA non controlla la connettività Internet. Ne ho trovati alcuni che usano il ping in questo modo: if [ 'ping google.com -c 4 | grep time' != "" ]; thenma a volte questo potrebbe non essere affidabile poiché il ping stesso potrebbe bloccarsi per qualche motivo (ad esempio, in attesa di un IO bloccato).

Qualche suggerimento sul modo corretto / affidabile per verificare la connettività Internet usando gli script? Devo usare alcuni pacchetti?

Deve essere in grado di controllare periodicamente, cronad esempio, quindi fare qualcosa quando la connessione si interrompe come invokeifup --force [interface]

Risposte:


29

Test della connettività IPv4

Se la tua rete lascia passare i ping, prova a eseguire il ping 8.8.8.8 (un server gestito da 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

Test di connettività IP e DNS

Se si desidera che il test abbia esito positivo solo quando DNS funziona, utilizzare un nome host.

if ping -q -c 1 -W 1 google.com >/dev/null; then
  echo "The network is up"
else
  echo "The network is down"
fi

Test della connettività web

Alcuni firewall bloccano i ping. Alcuni luoghi hanno un firewall che blocca tutto il traffico tranne tramite un proxy web. Se si desidera testare la connettività Web, è possibile effettuare una richiesta 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

È possibile che si desideri incorporare la convalida di una connessione fisica (livello OSI 1) prima di qualsiasi controllo del livello 3 OSI utilizzando ethtool; $ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
jas-

Puoi spiegare lo scopo di aggiungere questo per favore>/dev/null
Amine Harbaoui,

@AmineHarbaoui - >/dev/nullreindirizza l'output standard a /dev/null, il dispositivo null , che lo elimina poiché non è desiderato in questo caso (tutto ciò che ci interessa sono i valori di uscita dei comandi). Invece, dalle echolinee viene prelevato un output più applicabile .
Adam Katz,

27

Consiglio vivamente di non utilizzare pingper determinare la connettività. Ci sono troppi amministratori di rete che disabilitano l' ICMP (il protocollo che utilizza) a causa delle preoccupazioni relative agli attacchi di ping flood provenienti dalle loro reti.

Invece, utilizzo un test rapido di un server affidabile su una porta che puoi aspettarti di essere aperto:

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

Questo utilizza netcat ( nc) nella sua modalità di scansione delle porte , un poke rapido ( -zè la modalità zero-I / O [usata per la scansione] ) con un timeout rapido ( -w 1attende al massimo un secondo). Controlla Google sulla porta 443 (HTTPS).

Ho usato HTTPS anziché HTTP come uno sforzo per proteggere da portali captive e proxy trasparenti che possono rispondere sulla porta 80 (HTTP) per qualsiasi host. Ciò è meno probabile quando si utilizza la porta 443 poiché si verificherebbe una mancata corrispondenza del certificato, ma si verifica comunque.

Se vuoi metterti alla prova, dovrai convalidare la sicurezza sulla connessione:

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

Questo verifica la presenza di una connessione (piuttosto che attendere il timeout di openssl) e quindi effettua l'handshake SSL, digitando sulla fase di verifica. Esce silenziosamente ("vero") se la verifica era "OK" oppure esce con un errore ("falso"), quindi segnaliamo il risultato.


5
Rispetto Gillies, tuttavia questa è la risposta giusta.
Gwillie,

3
aggiungere -dad esempio nc -dzw1anche in modo che non ascolti STDIN e si blocchi indefinitamente in uno script. e forse utilizzare 8.8.8.8 invece di google.com per salvare una ricerca. nc -dzw1 8.8.8.8 443
dezza,

Non sono sicuro di quanto sia affidabile il risolutore DNS di Google nel servire HTTPS. Il server google.com dovrebbe essere più affidabile per HTTPS (a meno che tu non sia in Cina, ma entrambi sono probabilmente bloccati). Non ho mai avuto bisogno dei -dmiei script, forse perché non ho mai avuto una pipeline inutilizzata. Dovrebbe essere sicuro aggiungere.
Adam Katz,

1
@dezza - -w 1costa ancora un secondo quando non c'è connettività, anche se forse hai ncqualche tipo di problema oscuro da qualche parte. Se hai installato una versione recente di nmap, puoi invece fare ncat --send-only --recv-only -w 334msper ridurre il tempo di errore a un terzo di nc(ho scoperto che 334ms è un buon tempo di attesa).
Adam Katz,

1
@dezza - Non so perché ciò accada sia su ncat di nmap che su netcat (nc) per quel sistema. Potrebbe esserci qualcosa di strano nella tua rete o su quel sistema BSD. Sentiti libero di creare una nuova domanda unix.stackexchange e ottenere più di un semplice sguardo su quel problema. In tal caso, collegalo nei commenti qui e collega questa discussione alla tua nuova domanda.
Adam Katz,

9

Ho realizzato uno script che utilizza diversi modi per verificare la connessione a Internet (ping, nc e curl, grazie a Adam Katz, Gilles e Archemar). Spero che qualcuno lo trovi utile. Sentiti libero di modificarlo a tuo piacimento / ottimizzalo.

Controlla il gateway, il DNS e la connessione Internet (utilizzando curl, nc e ping). Mettilo in un file e rendilo eseguibile (di solito 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

Bello ! Grazie ! A cosa dovremmo impostare il gateway $GW?
Ciprian Tomoiagă,

@CiprianTomoiaga Non è necessario, /sbin/ip route | awk '/default/ { print $3 }'ottiene l'indirizzo gateway dall'interfaccia (si spera) primaria. Se lo desideri, puoi impostare tu stesso l'indirizzo IP del gateway.
PNDA

Grazie per questo! Ciò che mi manca, tuttavia, è la possibilità di archiviare le interruzioni di Internet in un file txt e un'e-mail automatizzata al mio ISP.
UR e

2

ci sono molti IP su Internet, un approccio leggero è quello di eseguire il ping di alcuni di essi

 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

una risposta più completa potrebbe essere ottenere pagine usando wget

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

dove

  • parse è un programma che scrivi che garantisce che google.txt non sia una versione (troppo vecchia) memorizzata nella cache di google.com

1

grazie al tuo contributo da parte di ogni utente e altra rete, sono riuscito a completare questo script in 3 giorni. e lo lascerò libero per il suo uso.

questo script automatizza il rinnovo dell'indirizzo IP quando si perde la connessione, lo fa in modo persistente.

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


Cosa renderebbe migliore questa risposta: (1) Spiegare come funziona lo script. (Sembra che l'utente debba modificare lo script se la sua interfaccia di rete viene chiamata in modo diverso da eth0, ma questo non è menzionato.) (2) Uso dell'inglese. (3) Mettere tutte le variabili di shell (es. "$HOST", "$LINE1"E "$LOG") tra virgolette. (4) Impostare LINE2o non utilizzarlo. (Sospetto che tu sia LINE1 /  LINE2confuso con inet4 /  inet6.) ... (proseguendo)
G-Man dice "Reinstate Monica" il

(Continua) ... (5) Visualizzazione effettiva dell'ora corrente quando si dice che si sta visualizzando l'ora corrente, piuttosto che catturare l'ora di inizio dello script e visualizzarla per tutta la sua durata. (6) Penso che ci fosse qualcos'altro, ma non lo vedo ora.
G-Man dice 'Reinstate Monica' il

È in spagnolo perché è nella mia lingua, ma posso correggerlo in inglese. $ HOST è l'indirizzo da provare. $ LINE1 è la connessione Internet connessa dall'adattatore eth0. $ LINE2 è la connessione Internet connessa dall'adattatore eth1 se si dispone di 2 linee Internet, ma si consiglia di lasciarlo disabilitato. La data, se si verifica che mantenga la stessa ora e data da quando ho avviato lo script, devo correggere quel problema. Questo fine settimana ho corretto il problema.
John Llewelyn,

Ok G-Man, ho apportato alcune modifiche, devo ancora correggere la data e migliorare alcune cose.
John Llewelyn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.