Script de shell: maneira correta de verificar a conectividade com a Internet?

26

Encontrei scripts que dizem que verificam a conectividade com a Internet. Alguns verificam o endereço IP se a interface estiver ativa, mas não verifica a conectividade com a Internet. Eu encontrei alguns que usam ping como este: if [ 'ping google.com -c 4 | grep time' != "" ]; thenmas às vezes isso pode não ser confiável, já que o ping pode travar por algum motivo (por exemplo, aguardando alguma E / S travada).

Alguma sugestão sobre a maneira correta / confiável de verificar a conectividade da Internet usando scripts? Eu tenho que usar alguns pacotes?

Ele precisa verificar periodicamente com, cronpor exemplo, algo quando a conexão cair como invocarifup --force [interface]

PNDA
fonte

Respostas:

29

Testando a conectividade IPv4

Se sua rede permitir pings, tente executar o ping 8.8.8.8 (um servidor executado pelo 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

Testando conectividade IP e DNS

Se você deseja que o teste seja bem-sucedido apenas quando o DNS também estiver funcionando, use um nome de 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

Testando a conectividade da Web

Alguns firewalls bloqueiam pings. Alguns lugares têm um firewall que bloqueia todo o tráfego, exceto por meio de um proxy da web. Se você deseja testar a conectividade da Web, pode fazer uma solicitação 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
Gilles 'SO- parar de ser mau'
fonte
Você pode incorporar a validação de uma conexão física (camada 1 do OSI) antes de qualquer verificação da camada 3 do OSI usando o ethtool; $ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
jas-
Você pode explicar o propósito de adicionar isso, por favor>/dev/null
Amine Harbaoui
@AmineHarbaoui - >/dev/nullredireciona a saída padrão para /dev/nullo dispositivo nulo , que a descarta, pois não é desejada nesse caso (tudo o que nos interessa são os valores de saída dos comandos). Em vez disso, uma saída mais aplicável é obtida das echolinhas.
Adam Katz
27

Eu recomendo não usar pingpara determinar a conectividade. Existem muitos administradores de rede que desabilitam o ICMP (o protocolo usado) devido a preocupações com ataques de inundação de ping originados em suas redes.

Em vez disso, uso um teste rápido de um servidor confiável em uma porta que você pode esperar estar aberta:

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

Isso usa netcat ( nc) no modo de varredura de porta , um toque rápido ( -zé o modo de E / S zero [usado para varredura] ) com um tempo limite rápido ( -w 1aguarda no máximo um segundo). Ele verifica o Google na porta 443 (HTTPS).

Eu usei HTTPS em vez de HTTP como um esforço para proteger contra portais cativos e proxies transparentes que podem responder na porta 80 (HTTP) para qualquer host. Isso é menos provável ao usar a porta 443, pois haveria uma incompatibilidade de certificado, mas ainda acontece.

Se você quiser se provar contra isso, precisará validar a segurança na conexão:

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

Isso verifica se há uma conexão (em vez de aguardar o tempo limite do openssl) e, em seguida, efetua o handshake SSL, digitando a fase de verificação. Ele sai silenciosamente ("true") se a verificação foi "OK" ou sai com um erro ("false"), então relatamos a descoberta.

Adam Katz
fonte
5
Eu respeito Gillies, no entanto, esta é a resposta certa.
Gwillie
3
adicione, -dpor exemplo, nc -dzw1também, para não escutar STDIN e travar indefinidamente em um script. e talvez use 8.8.8.8 em vez de google.com para salvar uma pesquisa. nc -dzw1 8.8.8.8 443
Dezza
Não tenho certeza sobre a confiabilidade do resolvedor DNS do Google em servir HTTPS. O servidor do google.com deve ser mais confiável para HTTPS (a menos que você esteja na China, mas ambos provavelmente estão bloqueados). Eu nunca precisei -dnos meus scripts, talvez porque nunca tive um pipeline não utilizado. Isso deve ser seguro para adicionar.
Adam Katz
11
@dezza - -w 1ainda custa um segundo quando não há conectividade, embora talvez o seu nctenha algum tipo de problema obscuro em algum lugar. Se você possui uma versão recente do nmap instalada, pode ncat --send-only --recv-only -w 334msreduzir esse tempo de falha para um terço nc(descobri que 334ms é um bom tempo de espera).
Adam Katz
11
@dezza - Eu não sei por que isso está acontecendo com você no nmap do nmap e no netcat (nc) para esse sistema. Pode haver algo estranho acontecendo na sua rede ou no sistema BSD. Sinta-se livre para criar uma nova pergunta unix.stackexchange e obter mais do que apenas meus olhos nesse problema. Em caso afirmativo, vincule-o nos comentários aqui e vincule esse tópico à sua nova pergunta.
Adam Katz
9

Criei um script que usa várias maneiras de verificar a conexão à Internet (ping, nc e curl, graças a Adam Katz, Gilles e Archemar). Espero que alguém ache isso útil. Sinta-se livre para editá-lo ao seu gosto / otimizá-lo.

Verifica seu gateway, DNS e conexão à Internet (usando curl, nc e ping). Coloque isso em um arquivo e torne-o executável (geralmente 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
PNDA
fonte
Agradável ! Obrigado ! Para o que devemos configurar o gateway $GW?
Ciprian Tomoiagă
@CiprianTomoiaga Não há necessidade, /sbin/ip route | awk '/default/ { print $3 }'obtém o endereço do gateway da interface primária (espero). Se desejar, você mesmo pode definir o endereço IP do gateway.
PNDA
Obrigado por isso! O que eu sinto falta, porém, é a opção de armazenar interrupções da Internet em um arquivo txt e um email automatizado no meu ISP.
Rand #
2

existem muitos IPs na internet, uma abordagem leve é ​​fazer ping em alguns deles

 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

uma resposta mais completa pode estar recebendo páginas usando wget

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

Onde

  • análise é um programa que você escreve para garantir que o google.txt não seja uma versão em cache (muito antiga) do google.com
Archemar
fonte
1

graças às suas contribuições de cada usuário e de outra web, consegui concluir este script em três dias. e vou deixá-lo livre para o seu uso.

esse script automatiza a renovação do endereço IP quando a conexão é perdida, o faz persistentemente.

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

John Llewelyn
fonte
O que tornaria essa resposta melhor: (1) Explicando como o script funciona. (Parece que o usuário precisa editar o script se sua interface de rede for chamada de algo diferente eth0, mas isso não for mencionado.) (2) Usando o inglês. (3) Colocar todas as variáveis do shell (por exemplo, "$HOST", "$LINE1"e "$LOG") em aspas duplas. (4) Defina LINE2ou não use. (Eu suspeito que você tem LINE1 /  LINE2confundido com inet4 /  inet6.) ... (Cont)
G-Man diz que 'Reintegrar Monica'
(Continua)… (5) Exibindo a hora atual quando você diz que está exibindo a hora atual, em vez de capturar a hora em que o script é iniciado e exibi-lo durante toda a vida útil do script. (6) Acho que havia outra coisa, mas não a vejo agora.
G-Man diz 'Reinstate Monica'
Está em espanhol porque está no meu idioma, mas posso corrigi-lo em inglês. O $ HOST é o endereço para tentar. $ LINE1 é a conexão à Internet conectada pelo adaptador eth0. $ LINE2 é a conexão à Internet conectada pelo adaptador eth1, opcionalmente, se você tiver 2 linhas da Internet, mas é recomendável deixá-lo desativado. A data, se eu verificar se ele mantém a mesma hora e data desde que inicio o script, tenho que corrigir esse problema. Neste fim de semana eu corrijo o problema.
precisa
Ok G-Man, fiz algumas alterações, ainda preciso corrigir a data e melhorar algumas coisas.
John Llewelyn