Shell Scripting: ¿forma correcta de verificar la conectividad a Internet?

26

Encontré secuencias de comandos que dicen que comprueban la conectividad a Internet. Algunos verifican la dirección IP si la interfaz está activa PERO no verifica la conectividad a Internet. Encontré algunos que usan ping como este: if [ 'ping google.com -c 4 | grep time' != "" ]; thenpero a veces esto puede no ser confiable ya que el ping en sí mismo puede colgarse por alguna razón (por ejemplo, esperando algún IO atascado).

¿Alguna sugerencia sobre la forma adecuada / confiable de verificar la conectividad a Internet mediante scripts? ¿Tengo que usar algunos paquetes?

Necesita poder verificar periódicamente con, cronpor ejemplo, hacer algo cuando la conexión se cae como invocarifup --force [interface]

PNDA
fuente

Respuestas:

29

Prueba de conectividad IPv4

Si su red deja pasar pings, intente hacer ping a 8.8.8.8 (un servidor ejecutado por 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

Prueba de conectividad IP y DNS

Si solo desea que la prueba tenga éxito cuando DNS también está funcionando, use un nombre 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

Prueba de conectividad web

Algunos cortafuegos bloquean pings. Algunos lugares tienen un firewall que bloquea todo el tráfico, excepto a través de un proxy web. Si desea probar la conectividad web, puede realizar una solicitud 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- deja de ser malvado'
fuente
Es posible que desee incorporar la validación de una conexión física (capa 1 de OSI) antes de cualquier verificación de la capa 3 de OSI usando ethtool; $ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
jas-
¿Puede explicar el propósito de agregar esto, por favor>/dev/null
Amine Harbaoui
@AmineHarbaoui - >/dev/nullredirige la salida estándar para /dev/nullel dispositivo nulo , que dispone de ella, ya que no se desea en este caso (lo único que importa es los valores de salida de los comandos). En cambio, la salida más aplicable se toma de las echolíneas.
Adam Katz
27

Recomiendo no usar pingpara determinar la conectividad. Hay demasiados administradores de red que deshabilitan ICMP (el protocolo que usa) debido a las preocupaciones sobre los ataques de inundación de ping que se originan en sus redes.

En cambio, utilizo una prueba rápida de un servidor confiable en un puerto que puede esperar que esté abierto:

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

Esto usa netcat ( nc) en su modo de escaneo de puertos , un empuje rápido ( -zes el modo cero E / S [usado para escanear] ) con un tiempo de -w 1espera rápido ( espera como máximo un segundo). Comprueba Google en el puerto 443 (HTTPS).

He usado HTTPS en lugar de HTTP como un esfuerzo para proteger contra portales cautivos y proxies transparentes que pueden responder en el puerto 80 (HTTP) para cualquier host. Esto es menos probable cuando se usa el puerto 443, ya que habría una falta de coincidencia de certificados, pero aún así sucede.

Si desea probarse contra eso, deberá validar la seguridad en la conexión:

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

Esto busca una conexión (en lugar de esperar a que se abra el tiempo de espera de openssl) y luego realiza el protocolo de enlace SSL, ingresando la fase de verificación. Sale silenciosamente ("verdadero") si la verificación fue "OK" o si sale con un error ("falso"), entonces informamos el hallazgo.

Adam Katz
fuente
55
Respeto a Gillies, sin embargo, esta es la respuesta correcta.
gwillie
3
agregue, -dpor ejemplo, nc -dzw1también para que no escuche STDIN y se cuelgue indefinidamente en un script. y tal vez use 8.8.8.8 en lugar de google.com para guardar una búsqueda. nc -dzw1 8.8.8.8 443
dezza
No estoy seguro de cuán confiable es el solucionador DNS de Google para servir HTTPS. El servidor google.com debería ser más confiable para HTTPS (a menos que esté en China, pero es probable que ambos estén bloqueados). Nunca he necesitado -den mis scripts, quizás porque nunca he tenido una tubería no utilizada. Eso debería ser seguro para agregar.
Adam Katz
1
@dezza: -w 1todavía cuesta un segundo cuando no hay conectividad, aunque quizás nctenga algún tipo de problema oscuro en alguna parte. Si tiene instalada una versión reciente de nmap, puede ncat --send-only --recv-only -w 334msreducir el tiempo de falla a un tercio nc(he descubierto que 334 ms es un buen tiempo de espera).
Adam Katz
1
@dezza - No sé por qué eso te está sucediendo tanto en ncat como en netcat (nc) de nmap para ese sistema. Puede haber algo extraño en su red o en ese sistema BSD. Siéntase libre de crear una nueva pregunta de unix.stackexchange y obtener algo más que mis ojos sobre ese problema. Si lo hace, enlácelo en los comentarios aquí y vincule este hilo a su nueva pregunta.
Adam Katz
9

Hice un script que usa múltiples formas de verificar la conexión a Internet (ping, nc y curl, gracias a Adam Katz, Gilles y Archemar). Espero que alguien encuentre esto útil. Siéntase libre de editarlo a su gusto / optimizarlo.

Comprueba su puerta de enlace, DNS y conexión a Internet (usando curl, nc y ping). Ponga esto en un archivo y luego hágalo ejecutable (generalmente 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
fuente
Agradable ! Gracias ! ¿A qué debemos configurar la puerta $GWde entrada ?
Ciprian Tomoiagă
@CiprianTomoiaga No es necesario, /sbin/ip route | awk '/default/ { print $3 }'obtiene la dirección de la puerta de enlace desde la interfaz principal (con suerte). Si lo desea, puede configurar la dirección IP de la puerta de enlace usted mismo.
PNDA
¡Gracias por esto! Sin embargo, lo que extraño es la opción de almacenar interrupciones de Internet en un archivo txt y un correo electrónico automatizado a mi ISP.
Rhand
2

hay muchas IP en internet, un enfoque ligero es hacer ping a algunas de ellas

 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 respuesta más completa podría ser obtener páginas usando wget

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

dónde

  • parse es un programa que usted escribe que garantiza que google.txt no sea una versión en caché (demasiado antigua) de google.com
Archemar
fuente
1

Gracias a sus contribuciones de cada usuario y de otros sitios web, logré completar este script en 3 días. y lo dejaré libre para su uso.

Este script automatiza la renovación de la dirección IP cuando se pierde la conexión, lo hace de forma 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

John Llewelyn
fuente
Qué mejoraría esta respuesta: (1) Explicar cómo funciona el guión. (Parece que el usuario tiene que editar el script si su interfaz de red se llama de otra manera eth0, pero esto no se menciona). (2) Uso del inglés. (3) Poner todas las variables de shell (p. Ej. "$HOST", "$LINE1"Y "$LOG") entre comillas dobles. (4) Establezca LINE2o no lo use. (Sospecho que tienes LINE1 /  LINE2confundido con inet4 /  inet6.) ... (Continúa)
G-Man dice 'Restablecer a Monica' el
(Cont.) ... (5) En realidad, muestra la hora actual cuando dice que está mostrando la hora actual, en lugar de capturar la hora en que comienza el guión y lo muestra durante toda la vida útil del guión. (6) Creo que había algo más, pero ahora no lo veo.
G-Man dice 'reinstalar a Monica' el
Está en español porque está en mi idioma, pero puedo corregirlo en inglés. El $ HOST es la dirección para probar. $ LINE1 es la conexión a Internet que se conecta mediante el adaptador eth0. $ LINE2 es la conexión a Internet que se conecta mediante el adaptador eth1 opcionalmente si tiene 2 líneas de Internet, pero se recomienda que la deje deshabilitada. La fecha, si verifico que mantiene la misma hora y fecha desde que inicio el script, tengo que corregir ese problema. Este fin de semana corrijo el problema.
John Llewelyn
Ok G-Man, hice algunos cambios, todavía necesito corregir la fecha y mejorar algunas cosas.
John Llewelyn