Shell Scripting: Właściwy sposób sprawdzania łączności z Internetem?


26

Znalazłem skrypty, które mówią, że sprawdzają łączność z Internetem. Niektórzy sprawdzają adres IP, jeśli interfejs jest włączony, ALE nie sprawdza połączenia z Internetem. Znalazłem takie, które używają ping w ten sposób: if [ 'ping google.com -c 4 | grep time' != "" ]; thenale czasami może to być niewiarygodne, ponieważ sam ping może się zawiesić z jakiegoś powodu (np. Czekając na zablokowane IO).

Wszelkie sugestie na temat właściwego / niezawodnego sposobu sprawdzania łączności z Internetem za pomocą skryptów? Czy muszę korzystać z niektórych pakietów?

Musi być w stanie okresowo sprawdzać, cronna przykład, a następnie zrobić coś, gdy połączenie zostanie zerwane, jak na przykład invokeifup --force [interface]

Odpowiedzi:


29

Testowanie łączności IPv4

Jeśli sieć przepuszcza pakiety ping, spróbuj pingować 8.8.8.8 (serwer obsługiwany przez 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

Testowanie łączności IP i DNS

Jeśli chcesz, aby test zakończył się powodzeniem, gdy działa również DNS, użyj nazwy hosta.

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

Testowanie łączności internetowej

Niektóre zapory blokują pingi. Niektóre miejsca mają zaporę ogniową, która blokuje cały ruch, z wyjątkiem serwera proxy. Jeśli chcesz przetestować łączność internetową, możesz wysłać żądanie 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

Możesz włączyć walidację połączenia fizycznego (warstwa 1 OSI) przed wszelkimi sprawdzeniami warstwy 3 OSI przy użyciu ethtool; $ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
jas-

Czy możesz wyjaśnić cel dodania tego>/dev/null
Amine Harbaoui

@AmineHarbaoui - >/dev/nullprzekierowuje standardowe wyjście do /dev/nullZ urządzeniem zerowego , który unieszkodliwia go, ponieważ nie jest pożądany w tym przypadku (wszyscy dbamy o to wartości wyjściowe poleceń). Zamiast tego z echolinii pobierane są bardziej odpowiednie dane wyjściowe .
Adam Katz

27

Gorąco polecam przed użyciem pingw celu ustalenia łączności. Jest zbyt wielu administratorów sieci, którzy wyłączają ICMP (protokół, którego używa) ze względu na obawy związane z atakami ping powodziowymi pochodzącymi z ich sieci.

Zamiast tego korzystam z szybkiego testu niezawodnego serwera na porcie, którego można się spodziewać:

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

Korzysta z netcat ( nc) w trybie skanowania portów , szybkim wciskaniu ( -zto tryb zero-I / O [używany do skanowania] ) z szybkim limitem czasu ( -w 1trwa maksymalnie jedną sekundę). Sprawdza Google na porcie 443 (HTTPS).

Użyłem HTTPS zamiast HTTP jako próby ochrony przed niewoli portali i przezroczystych serwerów proxy, które mogą odpowiadać na porcie 80 (HTTP) dla dowolnego hosta. Jest to mniej prawdopodobne w przypadku korzystania z portu 443, ponieważ wystąpiłoby niedopasowanie certyfikatu, ale nadal tak się dzieje.

Jeśli chcesz się temu przeciwstawić, musisz zweryfikować bezpieczeństwo połączenia:

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

Spowoduje to sprawdzenie połączenia (zamiast oczekiwania na przekroczenie limitu czasu przez openssl), a następnie nawiązanie połączenia SSL, wpisanie na etapie weryfikacji. Po cichu kończy działanie („prawda”), jeśli weryfikacja była „OK” lub kończy się z błędem („fałsz”), wówczas zgłaszamy znalezisko.


5
Szanuję Gillies, ale to właściwa odpowiedź.
gwillie

3
dodaj -dnp., nc -dzw1aby nie nasłuchiwał STDIN i zawieszał się w skrypcie w nieskończoność. i może użyć 8.8.8.8 zamiast google.com, aby zapisać wyszukiwanie. nc -dzw1 8.8.8.8 443
dezza

Nie jestem pewien, jak niezawodny program rozpoznawania nazw DNS firmy Google obsługuje HTTPS. Serwer google.com powinien być bardziej niezawodny w przypadku HTTPS (chyba że jesteś w Chinach, ale oba są prawdopodobnie zablokowane). Nigdy nie potrzebowałem -dw swoich skryptach, być może dlatego, że nigdy nie miałem nieużywanego potoku. To powinno być bezpieczne do dodania.
Adam Katz

1
@dezza - -w 1nadal kosztuje sekundę, gdy nie ma łączności, choć być może masz ncgdzieś jakiś niejasny problem. Jeśli masz zainstalowaną najnowszą wersję nmap, możesz zamiast tego zrobić, ncat --send-only --recv-only -w 334msaby skrócić ten czas awarii do jednej trzeciej nc(odkryłem, że 334 ms to dobry czas oczekiwania).
Adam Katz

1
@dezza - Nie wiem, dlaczego tak się dzieje w przypadku ncat i netcat (nc) nmap dla tego systemu. W sieci lub systemie BSD może się dziać coś dziwnego. Utwórz nowe pytanie dotyczące unix.stackexchange i uzyskaj więcej niż tylko moje spojrzenie na ten problem. Jeśli tak, prosimy o link w komentarzach tutaj i link tego wątku do nowego pytania.
Adam Katz

9

Stworzyłem skrypt, który wykorzystuje wiele sposobów sprawdzania połączenia internetowego (ping, nc i curl, dzięki Adamowi Katzowi, Gillesowi i Archemarowi). Mam nadzieję, że ktoś uzna to za przydatne. Możesz go edytować według własnych upodobań / zoptymalizować.

Sprawdza bramę, DNS i połączenie internetowe (używając curl, nc i ping). Umieść to w pliku, a następnie uruchom go (zwykle 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

Miły ! Dziękuję Ci ! Do czego powinniśmy ustawić bramę $GW?
Ciprian Tomoiagă

@CiprianTomoiaga Nie ma potrzeby, /sbin/ip route | awk '/default/ { print $3 }'pobiera adres bramy z (mam nadzieję) głównego interfejsu. Jeśli chcesz, możesz samodzielnie ustawić adres IP bramy.
PNDA,

Dzięki za to! Brakuje mi jednak opcji przechowywania zakłóceń internetowych w pliku txt i zautomatyzowanej wiadomości e-mail do mojego dostawcy usług internetowych.
rhand

2

w Internecie jest wiele adresów IP, lekkim podejściem jest pingowanie niektórych z nich

 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

bardziej kompletną odpowiedzią może być uzyskiwanie stron wget

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

gdzie

  • parsuj to program, który piszesz, który zapewnia, że ​​google.txt nie jest (zbyt starą) wersją google.com w pamięci podręcznej

1

dzięki twojemu wkładowi od każdego użytkownika i innej sieci udało mi się ukończyć ten skrypt w ciągu 3 dni. i zostawię go za darmo dla jego użycia.

ten skrypt automatyzuje odnawianie adresu IP w przypadku utraty połączenia, robi to uporczywie.

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


Co poprawiłoby tę odpowiedź: (1) Wyjaśnienie działania skryptu. (Wygląda na to, że użytkownik musi edytować skrypt, jeśli jego interfejs sieciowy jest nazywany inaczej niż eth0, ale nie jest to wspomniane.) (2) Używanie języka angielskiego. (3) doprowadzanie wszystkich zmiennych powłoki (na przykład "$HOST", "$LINE1"i "$LOG") w cudzysłowach. (4) Ustaw LINE2albo nie używaj go. (Podejrzewam, że masz LINE1 /  LINE2mylić z inet4 /  inet6.) ... (ciąg dalszy)
G-Man mówi 'przywrócić Monica'

(Ciąg dalszy)… (5) Faktyczne wyświetlanie aktualnego czasu, gdy mówisz, że wyświetlasz aktualny czas, zamiast przechwytywania czasu rozpoczęcia skryptu i wyświetlania go przez cały okres jego działania. (6) Myślę, że było coś jeszcze, ale teraz tego nie widzę.
G-Man mówi „Przywróć Monikę”

Jest w języku hiszpańskim, ponieważ jest w moim języku, ale mogę to poprawić po angielsku. $ HOST to adres do wypróbowania. $ LINE1 to połączenie internetowe, które jest połączone przez adapter eth0. $ LINE2 to połączenie internetowe, które jest połączone opcjonalnie przez adapter eth1, jeśli masz 2 linie internetowe, ale zalecane jest pozostawienie go wyłączonego. Data, jeśli sprawdzę, czy zachowuje tę samą godzinę i datę od momentu uruchomienia skryptu, muszę rozwiązać ten problem. W ten weekend naprawiam problem.
John Llewelyn,

Ok, G-Man, wprowadziłem kilka zmian, wciąż muszę poprawić datę i poprawić niektóre rzeczy.
John Llewelyn
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.