Jak przetestować połączenie internetowe za pomocą basha?

113

Jak można przetestować połączenie internetowe bez pingowania jakiejś strony internetowej? Mam na myśli, co jeśli jest połączenie, ale strona nie działa? Czy istnieje sprawdzenie połączenia ze światem?

Lauriys
źródło
2
pingować kilka różnych witryn?
1
ale nie chcę pingować stron internetowych, nie ma innej opcji?
Lauriys
6
Chcę tylko zobaczyć, że może jest inny sposób!
Lauriys
2
Nie ma lepszego sposobu niż wysłanie i odebranie pojedynczego pakietu na zestaw adresów, o których wiesz, że nie przechodzą w tryb offline od razu. Innym sposobem jest sprawdzenie aktualnego ustawienia DNS, jeśli nie chcesz, aby aplikacja wysyłała pingi do bardziej publicznych domena.
Tamara Wijsman
14
Chcę wiedzieć, czy ktoś słucha bez wydawania dźwięku!
Kaz

Odpowiedzi:

131

Bez pingów

#!/bin/bash

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

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

-q : tryb ciszy

--spider : nie odbieraj, po prostu sprawdź dostępność strony

$? : kod powrotu powłoki

0 : kod powłoki „Wszystko OK”

Bez 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
user3439968
źródło
2
bardzo ładne ... ale oczywiście zakłada, że ​​pudełko ma wget. wbudowane urządzenia i co prawdopodobnie nie będzie. ;)
Eric Sebasta
5
Spróbuj tego: echo -e "POBIERZ google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968
1
tcping też by się tutaj przydał. (tcping www.yahoo.com 80) && echo „Witryna działa”
David Ramirez,
Wyjaśnienie if / else użyj tutaj wirh jest świetne. Dziękuję Ci !
Danijel-James W,
1
@ user3439968 Musisz dodać limit czasu, ncaby upewnić się, że upłynie limit czasu . coś w stylunc google.com 80 -w 10
kaptan
93

Pinguj domyślną bramę:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error
mateusza
źródło
14
dobra technika, można ją zmodyfikować w celu użycia w funkcji: function ping_gw() { ... && return 0 || return 1 }a następnie użyć w następujący sposób:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy
1
w systemie Mac OS to nie działa przez kopiowanie i wklejanie: "-bash: ip: nie znaleziono polecenia ping: niedozwolona opcja - w"
Benedikt S. Vogler
1
Daje fałszywy alarm, jeśli jest uruchamiany z gościa wirtualizacji, gdy host nie jest podłączony.
Teresa i Junior
1
Daje mi fałszywe negatywy na podstawowym systemie operacyjnym (0.4.1, Acer Aspire E 15)
Malcolm
1
Ostrożnie z tym. Właśnie to przetestowałem ifconfig down wlan0i nadal mam domyślną bramę i można ją pingować, mimo że w rzeczywistości nie mogę dotrzeć do świata zewnętrznego.
Bruno Bronosky
29

Super Podziękowania dla użytkownika somedrew za ich post tutaj: https://bbs.archlinux.org/viewtopic.php?id=55485 dnia 2008-09-20 02:09:48

Szukanie w / sys / class / net powinno być jednokierunkowe

Oto mój skrypt do testowania połączenia sieciowego innego niż pętla zwrotna. Używam poniższego w innym skrypcie, który mam do okresowego testowania, czy moja witryna jest dostępna. Jeśli NIE jest dostępne, wyskakujące okienko ostrzega mnie o problemie.

Poniższy skrypt uniemożliwia mi otrzymywanie wyskakujących wiadomości co pięć minut, gdy mój laptop nie jest podłączony do sieci.

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

Uwaga dla nowych użytkowników basha: ostatnia instrukcja „if” sprawdza, czy NIE [!] Jest w trybie online i kończy działanie, jeśli tak jest. Aby uzyskać więcej informacji, zobacz man bash i wyszukaj wyrażenie „Wyrażenia można łączyć”.

PS Wydaje mi się, że ping nie jest tutaj najlepszym rozwiązaniem, ponieważ ma na celu przetestowanie połączenia z określonym hostem, a NIE sprawdzenie, czy istnieje połączenie z jakąkolwiek siecią .

PPS Powyższe działa na Ubuntu 12.04. / Sys może nie istnieć w niektórych innych dystrybucjach. Zobacz poniżej:

Nowoczesne dystrybucje Linuksa zawierają katalog / sys jako wirtualny system plików (sysfs, porównywalny z / proc, który jest procfs), który przechowuje i umożliwia modyfikację urządzeń podłączonych do systemu, podczas gdy wiele tradycyjnych systemów operacyjnych UNIX i Unix / sys jako symboliczne łącze do drzewa źródeł jądra. [potrzebne źródło]

Z Wikipedii https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

Jesse
źródło
1
Ostrożnie teraz! ” cat /sys/class/net/wwan0/carrierNie działa na ubuntu 14.04 LTS.
dotnetCarpenter
1
Możesz chcieć wstawić 2>/dev/nullpo, cat /sys/class/net/$interface/carrieraby nie wyświetlać błędów w przypadku wyłączenia sieci.
jarno
25

Działa to zarówno w systemie MacOSX, jak i Linux:

#!/bin/bash

ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline
legel
źródło
Z wyjątkiem osx ( ping: invalid option -- w)
avishayp
fping google.comlub po prostu fping 8.8.8.8robi magię z bonusem, otrzymujesz kod statusu bez potrzeby testowania (" google.com is alive") ...
Roger
9

W Bash, używając jego opakowania sieciowego przez / dev / { udp , tcp } / host / port :

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

( :to Bash no-op, ponieważ chcesz tylko przetestować połączenie, ale nie przetwarzać).

Luchostein
źródło
7

Napisałem wcześniej skrypty, które po prostu używają telnetu do łączenia się z portem 80, a następnie przesyłają tekst:

HTTP/1.0 GET /index.html

a następnie dwie sekwencje CR / LF.

Pod warunkiem, że otrzymasz odpowiedź HTTP, możesz ogólnie założyć, że witryna działa.

paxdiablo
źródło
3
Po co odkrywać koło na nowo? curl i wget robią to doskonale.
Adam Rosenfield
6
Ponieważ wget i curl nie zawsze są dostępne (np. Ograniczenia w środowiskach korporacyjnych). Telnet był standardową częścią każdego systemu UNIX od czasu t = 0.
paxdiablo
Tak, telnetowanie było dość standardowym sposobem testowania połączeń od dłuższego czasu.
PTBNL
2
Słuszna uwaga, chociaż wget jest dość powszechny. Inną opcją jest netcat (nc), chociaż w tym przypadku nie jest to żadna poprawa w stosunku do telnetu.
Adam Rosenfield
7

Najlepsza odpowiedź pomija fakt, że możesz mieć idealnie stabilne połączenie z domyślną bramą, ale nie oznacza to automatycznie, że możesz rzeczywiście dotrzeć do czegoś w Internecie. OP pyta, jak może przetestować połączenie ze światem. Dlatego proponuję zmienić pierwszą odpowiedź, zmieniając adres IP bramy na znany adres IP (xyzw), który znajduje się poza siecią LAN.

Tak więc odpowiedź brzmiałaby:

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

Usunięcie również niekorzystnych znaków odwrotnych do podstawiania poleceń [1] .

Jeśli chcesz tylko upewnić się, że jesteś połączony ze światem przed wykonaniem kodu, możesz również użyć:

if ping -q -w 1 -c 1 x.y.z.w > /dev/null; then
    # more code
fi
Fuwan
źródło
6

upewnij się, że Twoja sieć zezwala na ruch TCP przychodzący i wychodzący, możesz odzyskać publiczny adres IP za pomocą następującego polecenia

curl ifconfig.co
WaiKit Kung
źródło
5

Wykonaj następujące polecenie, aby sprawdzić, czy witryna internetowa działa i jaki komunikat o stanie wyświetla serwer sieciowy:

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

Kod stanu „200 OK” oznacza, że ​​żądanie powiodło się i witryna internetowa jest osiągalna.

Chaminda Bandara
źródło
2
Lepszym wdrożeniem mogłoby byćcurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Luca Galasso,
4

Jeśli twój lokalny serwer nazw jest wyłączony,

ping 4.2.2.1

to łatwy do zapamiętania adres IP, który jest zawsze aktywny (w rzeczywistości jest to nawet serwer nazw).

ephemient
źródło
5
ping 8.8.8.8 (Google NS)
user3439968
4

Top głosowało odpowiedź nie działa dla MacOS więc dla tych na mac, ja z powodzeniem przetestowane w ten sposób:

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

testowano na MacOS High Sierra 10.12.6

Francisc0
źródło
2
Zmień routepolecenie na, route -n get default 2> /dev/null | grep gatewayaby uniknąć zapisywania błędu w stderr w trybie offline.
devstuff
4

Ten skrypt bash stale sprawdza dostęp do Internetu i wydaje dźwięk, gdy Internet jest dostępny.

#!/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
Arjun G Perambra
źródło
3

najkrótsza droga: fping 4.2.2.1=> „4.2.2.1 żyje”

Wolę to, ponieważ jest to szybsze i mniej szczegółowe wyjście niż ping, wadą jest to, że będziesz musiał go zainstalować.

możesz użyć dowolnego publicznego DNS zamiast określonej witryny internetowej.

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

-q zwraca kod zakończenia, więc pokazuję tylko przykład uruchomienia czegoś, co jest online.

do zainstalowania na komputerze Mac: brew install fping; na ubuntu:sudo apt-get install fping

Alex Moore-Niemi
źródło
2

Ping został zaprojektowany tak, aby robić dokładnie to, czego szukasz. Jeśli jednak witryna blokuje echo ICMP, zawsze możesz wykonać telnet na porcie 80 jakiejś lokacji, wget lub curl.

nikudesu
źródło
2

Sprawdzanie strony indeksu Google to inny sposób:

#!/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
dm76
źródło
2

Podobnie jak odpowiedź @ Jesse , ta opcja może być znacznie szybsza niż jakiekolwiek rozwiązanie używające pingi być może nieco bardziej wydajna niż odpowiedź @ Jesse .

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

Wyjaśnienie:

To polecenie używa findwith -execdo uruchamiania polecenia na wszystkich plikach, które nie są wymienione *lo*w /sys/class/net/. Powinny to być łącza do katalogów zawierających informacje o dostępnych interfejsach sieciowych na komputerze.

Uruchomione polecenie jest shpoleceniem, które sprawdza zawartość pliku carrierw tych katalogach. Wartość $interface/carrierma 3 znaczenia - Cytując :

Wygląda na to, że istnieją trzy stany:

  • ./carrier nieczytelne (na przykład, gdy interfejs jest wyłączony w Menedżerze sieci).
  • ./carrier zawiera "1" (gdy interfejs jest aktywny i jest podłączony do sieci WiFi)
  • ./carrier zawierają „0” (gdy interfejs jest aktywny i nie jest połączony z siecią WiFi)

Pierwsza opcja nie została uwzględniona w odpowiedzi @ Jesse . shKomenda jest rozłożony na zewnątrz:

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

catjest używany do sprawdzania zawartości carrieri przekierowywania wszystkich danych wyjściowych na standardowe wyjście, nawet jeśli nie powiedzie się, ponieważ plik nie jest czytelny. Jeśli grep -qznajdzie "1"wśród tych plików, oznacza to, że jest podłączony co najmniej 1 interfejs. Kod wyjścia grep -qbędzie ostatecznym kodem wyjścia.

Stosowanie

Na przykład, używając statusu wyjścia tego polecenia, możesz go użyć do uruchomienia gnubiff w swoim ~/.xprofiletylko wtedy, gdy masz połączenie z Internetem.

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 &

Odniesienie

Doron Behar
źródło
1

Pong nie oznacza, że ​​usługa internetowa na serwerze jest uruchomiona; oznacza to po prostu, że serwer odpowiada na echo ICMP. Poleciłbym użyć curl i sprawdzić jego wartość zwracaną.

tomoe
źródło
0

Jeśli Twoim celem jest sprawdzenie dostępu do Internetu , wiele z istniejących odpowiedzi na to pytanie jest błędnych. Kilka rzeczy, o których powinieneś wiedzieć:

  1. Komputer może być podłączony do sieci bez dostępu do Internetu
  2. Możliwe, że serwer zostanie wyłączony, a cały Internet nie będzie niedostępny
  3. Portal dostępowy może zwrócić odpowiedź HTTP na dowolny adres URL, nawet jeśli nie masz dostępu do internetu

Mając to na uwadze, uważam, że najlepszą strategią jest skontaktowanie się z kilkoma witrynami za pośrednictwem połączenia HTTPS i zwrócenie wartości true, jeśli którakolwiek z tych witryn odpowie.

Na przykład:

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
}

Stosowanie:

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

Kilka uwag na temat tego podejścia:

  1. Jest odporny na wszystkie fałszywie pozytywne i negatywne cechy, które opisałem powyżej
  2. Wszystkie żądania odbywają się równolegle, aby zmaksymalizować prędkość
  3. Zwróci fałsz, jeśli technicznie masz dostęp do Internetu, ale DNS nie działa lub ustawienia sieci są w inny sposób pomieszane, co moim zdaniem jest rozsądne w większości przypadków
Ajedi32
źródło
Kod powrotu z curl nie jest testowany. W moim systemie, jeśli sieć nie jest dostępna, curl daje rc = 6 (nieudane rozpoznawanie nazw DNS), ale ten kod nadal wyświetla komunikat „Połączono z Internetem”.
ceperman
@ceperman Kod powrotu dla curl jest testowany w wierszu, w którym jest napisany if wait $pid;. Nie mam pojęcia, dlaczego to nie działa w twoim systemie. Czy na pewno używasz basha?
Ajedi, 32
@ceperman Inna możliwość; chyba jeden z adresów URL na liście u góry faktycznie robi sukces powrotu dla ciebie, chociaż inni zawodzą rozpoznawania nazw?
Ajedi, 32
2
Mój bash jest dość prosty, więc czytam dalej waiti rozumiem, że kod powrotu jest rzeczywiście testowany. Ponownie skopiowałem Twój kod i dziś działa - ups! Musiałem coś schrzanić ostatnim razem, chociaż nie rozumiem, co i jak. Niemniej jednak mea culpa. Przeprosiny.
ceperman
-1

Jest to znacznie szybsze niż jakiekolwiek zamieszczone tutaj rozwiązanie i może być również używane do testowania określonego hosta .

Sztuczka polega na rozwiązaniu adresu IP przy użyciu mniej obciążonego solwera DNS niż ten używany przez 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
}
Alberto Salvia Novella
źródło
2
Chociaż ten link może odpowiedzieć na pytanie, lepiej jest zawrzeć tutaj zasadnicze części odpowiedzi i podać link do odniesienia. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie. - Z recenzji
David Buck
Nie dotyczy to tej konkretnej sytuacji.
Alberto Salvia Novella