Come testare una connessione Internet con bash?


113

Come si può testare una connessione Internet senza eseguire il ping di un sito Web? Voglio dire, cosa succede se c'è una connessione ma il sito è inattivo? C'è un controllo per una connessione con il mondo?


2
eseguire il ping di diversi siti diversi?

1
ma non voglio eseguire il ping di siti Web, non ci sono altre opzioni?
lauriys

6
Voglio solo vedere che forse ci sono altri modi!
lauriys

2
Non c'è modo migliore che inviare e ricevere un singolo pacchetto a un insieme di indirizzi che sai per non andare offline tutto in una volta, un altro modo è controllare il tuo DNS impostato corrente se non vuoi che la tua applicazione esegua un ping più pubblico dominio.
Tamara Wijsman

14
Voglio sapere se qualcuno sta ascoltando, senza emettere un suono!
Kaz

Risposte:


131

Senza ping

#!/bin/bash

wget -q --spider http://google.com

if [ $? -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi

-q : modalità silenziosa

--spider : non ottenere, controlla solo la disponibilità della pagina

$? : codice di ritorno della shell

0 : codice shell "All OK"

Senza 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

2
molto carino ... ma ovviamente si presume che la scatola abbia wget. dispositivi embedded e quant'altro probabilmente non lo faranno. ;)
Eric Sebasta

5
Prova questo: echo -e "GET google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968

1
tcping sarebbe anche di aiuto qui. (tcping www.yahoo.com 80) && echo "Site is up"
David Ramirez

L'istruzione if / else usata qui con una spiegazione è ottima. Grazie !
Danijel-James W

1
@ user3439968 È necessario aggiungere timeout a ncper assicurarsi che scada . qualcosa comenc google.com 80 -w 10
kaptan

93

Eseguire il ping del gateway predefinito:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error

14
buona tecnica, può essere modificata per essere utilizzata in una funzione: function ping_gw() { ... && return 0 || return 1 }e quindi usata così:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy

1
su mac os questo non funziona tramite copia-incolla: "-bash: ip: comando non trovato ping: opzione illegale - w"
Benedikt S. Vogler

1
Fornisce un falso allarme se eseguito da un guest di virtualizzazione mentre l'host non è connesso.
Teresa e Junior

1
Mi dà falsi negativi su sistema operativo elementare (0.4.1, Acer Aspire E 15)
Malcolm

1
Stai attento con questo. L'ho appena testato in questo modo ifconfig down wlan0e ho ancora un gateway predefinito ed è eseguibile il ping, anche se in realtà non posso raggiungere il mondo esterno.
Bruno Bronosky

29

Super Grazie all'utente somedrew per il suo post qui: https://bbs.archlinux.org/viewtopic.php?id=55485 su 2008-09-20 02:09:48

Cercare in / sys / class / net dovrebbe essere unidirezionale

Ecco il mio script per testare una connessione di rete diversa dal loopback. Uso quanto segue in un altro script che ho per testare periodicamente se il mio sito web è accessibile. Se NON è accessibile, una finestra popup mi avvisa di un problema.

Lo script seguente mi impedisce di ricevere messaggi popup ogni cinque minuti ogni volta che il mio laptop non è connesso alla rete.

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

Nota per chi non conosce bash: l'istruzione finale "if" verifica se NON [!] Online ed esce se questo è il caso. Vedi man bash e cerca "Le espressioni possono essere combinate" per maggiori dettagli.

PS Penso che il ping non sia la cosa migliore da usare qui perché mira a testare una connessione a un particolare host NON testare se c'è una connessione a una rete di qualsiasi tipo.

PPS Il precedente funziona su Ubuntu 12.04 Il / sys potrebbe non esistere su alcune altre distribuzioni. Vedi sotto:

Le moderne distribuzioni Linux includono una directory / sys come file system virtuale (sysfs, paragonabile a / proc, che è un procfs), che memorizza e consente la modifica dei dispositivi collegati al sistema, mentre molti sistemi operativi tradizionali UNIX e simili a Unix utilizzano / sys come collegamento simbolico all'albero dei sorgenti del kernel. [citazione necessaria]

Da Wikipedia https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard


1
Attento adesso! " cat /sys/class/net/wwan0/carrierNon funziona su ubuntu 14.04 LTS.
dotnetCarpenter

1
Si consiglia di inserire 2>/dev/nulldopo cat /sys/class/net/$interface/carrierper non avere output di errore nel caso in cui la rete sia disabilitata.
jarno

25

Funziona sia su MacOSX che su Linux:

#!/bin/bash

ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline

Fatta eccezione per osx ( ping: invalid option -- w)
avishayp

fping google.como semplicemente fping 8.8.8.8fa la magia con un bonus, ottieni il codice di stato senza bisogno di testarlo (" google.com is alive") ...
Roger

9

In Bash, utilizzando il suo wrapper di rete tramite / dev / { udp , tcp } / host / port :

if : >/dev/tcp/8.8.8.8/53; then
  echo 'Internet available.'
else
  echo 'Offline.'
fi

( :è il Bash no-op, perché vuoi solo testare la connessione, ma non l'elaborazione.)


7

Ho già scritto script prima di utilizzare semplicemente telnet per connettersi alla porta 80, quindi trasmettere il testo:

HTTP/1.0 GET /index.html

seguito da due sequenze CR / LF.

A condizione che tu riceva una qualche forma di risposta HTTP, puoi generalmente presumere che il sito funzioni.


3
Perché reinventare la ruota? curl e wget lo fanno entrambi perfettamente.
Adam Rosenfield

6
Perché wget e curl non sono sempre disponibili (ad esempio, restrizioni negli ambienti aziendali). Telnet è stato una parte standard di ogni UNIX sin dal tempo t = 0.
paxdiablo

Sì, il telnet è stato un modo abbastanza standard per testare le connessioni per un bel po '.
PTBNL

2
Buon punto, anche se wget è abbastanza comune. Un'altra opzione è netcat (nc), sebbene in questo caso non sia un miglioramento rispetto a telnet.
Adam Rosenfield

7

La risposta migliore manca del fatto che puoi avere una connessione perfettamente stabile al tuo gateway predefinito, ma ciò non significa automaticamente che puoi effettivamente raggiungere qualcosa su Internet. L'OP chiede come può testare una connessione con il mondo. Quindi suggerisco di modificare la risposta principale cambiando l'IP del gateway in un IP noto (xyzw) che si trova al di fuori della tua LAN.

Quindi la risposta sarebbe:

ping -q -w 1 -c 1 x.y.z.w > /dev/null && echo ok || echo error

Rimuovendo anche i backtick non consigliati per la sostituzione dei comandi [1] .

Se vuoi solo assicurarti di essere connesso al mondo prima di eseguire del codice puoi anche usare:

if ping -q -w 1 -c 1 x.y.z.w > /dev/null; then
    # more code
fi

6

assicurati che la tua rete consenta il traffico TCP in entrata e in uscita, quindi potresti recuperare il tuo IP pubblico con il seguente comando

curl ifconfig.co

5

Eseguire il comando seguente per verificare se un sito Web è attivo e quale messaggio di stato sta mostrando il server Web:

$ curl -Is http://www.google.com | head -1 HTTP/1.1 200 OK

Il codice di stato "200 OK" significa che la richiesta è andata a buon fine e che un sito web è raggiungibile.


2
Una migliore implementazione potrebbe esserecurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Luca Galasso

4

Se il tuo server dei nomi locale è inattivo,

ping 4.2.2.1

è un IP sempre attivo facile da ricordare (in realtà è anche un server dei nomi).


5
ping 8.8.8.8 (Google NS)
user3439968

4

La risposta più votata non funziona per MacOS, quindi per quelli su un Mac, ho testato con successo questo:

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

testato su MacOS High Sierra 10.12.6


2
Modificare il routecomando in route -n get default 2> /dev/null | grep gatewayper evitare di scrivere un errore su stderr quando offline.
devstuff

4

Questo script bash controlla continuamente la presenza di Internet ed emette un segnale acustico quando Internet è disponibile.

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

3

modo più breve: fping 4.2.2.1=> "4.2.2.1 è vivo"

lo preferisco in quanto è un output più veloce e meno dettagliato di ping , lo svantaggio è che dovrai installarlo.

è possibile utilizzare qualsiasi DNS pubblico anziché un sito Web specifico.

fping -q google.com && echo "do something because you're connected!"

-q restituisce un codice di uscita, quindi sto solo mostrando un esempio di esecuzione di qualcosa che sei online.

da installare su Mac: brew install fping; su ubuntu:sudo apt-get install fping


2

Ping è stato progettato per fare esattamente quello che stai cercando di fare. Tuttavia, se il sito blocca l'eco ICMP, puoi sempre eseguire il telnet sulla porta 80 di qualche sito, wget o curl.


2

Controllare la pagina dell'indice di Google è un altro modo per farlo:

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

2

Analogamente alla risposta di @ Jesse , questa opzione potrebbe essere molto più veloce di qualsiasi soluzione che utilizza pinge forse leggermente più efficiente della risposta di @ Jesse .

find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1' {} \; | grep -q '1'

explenation:

Questo comando utilizza findcon -execper eseguire il comando su tutti i file non nominati *lo*in/sys/class/net/ . Questi dovrebbero essere collegamenti a directory contenenti informazioni sulle interfacce di rete disponibili sulla macchina.

Il comando in esecuzione è un shcomando che controlla il contenuto del file carrierin quelle directory. Il valore di $interface/carrierha 3 significati - Citando :

Sembra che ci siano tre stati:

  • ./carrier non leggibile (ad esempio quando l'interfaccia è disabilitata in Network Manager).
  • ./carrier contiene "1" (quando l'interfaccia è attivata ed è collegata a una rete WiFi)
  • ./carrier contiene "0" (quando l'interfaccia è attivata e non è collegata a una rete WiFi)

La prima opzione non è stata presa in considerazione nella risposta di @ Jesse . Il shcomando con striping è:

# Note: $0 == $interface
cat "$0"/carrier 2>&1

catviene utilizzato per controllare il contenuto carriere reindirizzare tutto l'output allo standard output anche quando fallisce perché il file non è leggibile. Se grep -qtrova "1"tra quei file significa che c'è almeno 1 interfaccia collegata. Il codice di uscita di grep -qsarà il codice di uscita finale.

uso

Ad esempio, usando lo stato di uscita di questo comando, puoi usarlo per avviare uno gnubiff nel tuo ~/.xprofilesolo se hai una connessione Internet.

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 &

Riferimento


1

Pong non significa che il servizio web sul server sia in esecuzione; significa semplicemente che il server sta rispondendo all'eco dell'ICMP. Consiglierei di usare curl e di controllare il suo valore di ritorno.


0

Se il tuo obiettivo è verificare effettivamente l' accesso a Internet , molte delle risposte esistenti a questa domanda sono errate. Alcune cose di cui dovresti essere a conoscenza:

  1. È possibile che il tuo computer sia connesso a una rete senza che la rete abbia accesso a Internet
  2. È possibile che un server non sia attivo senza che l'intera Internet sia inaccessibile
  3. È possibile che un captive portal restituisca una risposta HTTP per un URL arbitrario anche se non si dispone dell'accesso a Internet

Con questo in mente, credo che la migliore strategia sia contattare diversi siti tramite una connessione HTTPS e restituire true se uno di questi siti risponde.

Per esempio:

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
}

Uso:

if connected_to_internet; then
  echo "Connected to internet"
else
  echo "No internet connection"
fi

Alcune note su questo approccio:

  1. È robusto contro tutti i falsi positivi e negativi che ho descritto sopra
  2. Le richieste avvengono tutte in parallelo per massimizzare la velocità
  3. Restituirà falso se tecnicamente hai accesso a Internet ma il DNS non è funzionante o le tue impostazioni di rete sono altrimenti incasinate, cosa che penso sia una cosa ragionevole da fare nella maggior parte dei casi

Il codice di ritorno da curl non viene testato. Sul mio sistema se la rete non è disponibile, curl dà rc = 6 (risoluzione DNS fallita) ma questo codice riporta ancora "Connesso a Internet".
ceperman

@ceperman Il codice di ritorno per curl viene testato sulla riga in cui dice if wait $pid;. Non ho idea del motivo per cui non funziona sul tuo sistema. Sei sicuro di usare bash?
Ajedi32

@ceperman Un'altra possibilità; forse uno degli URL nella lista in alto in realtà fa il successo di ritorno per voi, anche se gli altri stanno fallendo la risoluzione dei nomi?
Ajedi32

2
Il mio bash è piuttosto semplice, quindi ho letto waite ora capisco che il codice di ritorno è effettivamente in fase di test. Ho ricopiato il tuo codice e oggi funziona - whoops! Devo aver incasinato qualcosa l'ultima volta anche se non riesco a capire cosa o come. Tuttavia, mea culpa. Scuse.
ceperman


-1

Questo è notevolmente più veloce di qualsiasi soluzione pubblicata qui e può essere utilizzato anche per testare un host specifico .

Il trucco sta nel risolvere l'IP utilizzando un risolutore DNS meno occupato di quello impiegato da ping:

validateConnection () {
    host="${1}"
    ip=$(getent ahostsv4 "${host}" | awk '{ print $1 }' | head -n1)
    ping -c1 "${ip}" 2>&1 >"/dev/null"

    if [ "${?}" -ne 0 ]; then
        echo "No connection to: ${host}" >&2
        exit 1
    fi
}

2
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere le parti essenziali della risposta qui e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia. - Dalla recensione
David Buck

Non si applica a questa situazione particolare.
Alberto Salvia Novella
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.