¿Cómo probar una conexión a Internet con bash?

113

¿Cómo se puede probar una conexión a Internet sin hacer ping a algún sitio web? Quiero decir, ¿qué pasa si hay una conexión pero el sitio no funciona? ¿Hay alguna verificación de conexión con el mundo?

lauriys
fuente
2
hacer ping a varios sitios diferentes?
1
pero no quiero hacer ping a sitios web, ¿no hay otra opción?
lauriys
6
¡Solo quiero ver que tal vez haya otra manera!
lauriys
2
No hay mejor manera que enviar y recibir un solo paquete a un conjunto de direcciones que sabe que no deben desconectarse todas a la vez, otra forma es verificar su conjunto de DNS actual si no desea que su aplicación haga ping a un público más dominio.
Tamara Wijsman
14
Quiero saber si alguien está escuchando, ¡sin hacer ruido!
Kaz

Respuestas:

131

Sin ping

#!/bin/bash

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

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

-q : modo de silencio

--spider : no lo consigas, solo verifica la disponibilidad de la página

PS: código de retorno de shell

0 : código de shell "Todo OK"

Sin 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
usuario3439968
fuente
2
muy bonito ... pero, por supuesto, se supone que la caja tiene wget. dispositivos integrados y otras cosas probablemente no lo harán. ;)
Eric Sebasta
5
Pruebe esto: echo -e "GET google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968
1
tcping también sería de ayuda aquí. (tcping www.yahoo.com 80) && echo "El sitio está activo"
David Ramirez
La instrucción if / else que se usa aquí con una explicación es excelente. Gracias !
Danijel-James W
1
@ user3439968 Debe agregar tiempo de espera ncpara asegurarse de que se agote. algo así comonc google.com 80 -w 10
kaptan
93

Haga ping a su puerta de enlace predeterminada:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error
mateusza
fuente
14
buena técnica, se puede modificar para usarla en una función: function ping_gw() { ... && return 0 || return 1 }y luego usarla así:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy
1
en mac os esto no funciona a través de copiar y pegar: "-bash: ip: comando no encontrado ping: opción ilegal - w"
Benedikt S. Vogler
1
Da una falsa alarma si se ejecuta desde un invitado de virtualización mientras el host no está conectado.
Teresa e Junior
1
Me da falsos negativos en el sistema operativo elemental (0.4.1, Acer Aspire E 15)
Malcolm
1
Tenga cuidado con esto. Acabo de probar esto haciendo ifconfig down wlan0y todavía tengo una puerta de enlace predeterminada y se puede hacer ping, aunque de hecho no puedo llegar al mundo exterior.
Bruno Bronosky
29

Super Gracias al usuario somedrew por su publicación aquí: https://bbs.archlinux.org/viewtopic.php?id=55485 en 2008-09-20 02:09:48

Mirar en / sys / class / net debe ser de una forma

Aquí está mi secuencia de comandos para probar una conexión de red que no sea el bucle de retorno. Utilizo lo siguiente en otro script que tengo para probar periódicamente si mi sitio web es accesible. Si NO es accesible, una ventana emergente me avisa de un problema.

El siguiente script me impide recibir mensajes emergentes cada cinco minutos cuando mi computadora portátil no está conectada a la red.

#!/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 para los nuevos en bash: La declaración final 'if' prueba si NO [!] Está en línea y sale si este es el caso. Consulte man bash y busque "Las expresiones se pueden combinar" para obtener más detalles.

PD: Creo que ping no es lo mejor para usar aquí porque tiene como objetivo probar una conexión a un host en particular, NO probar si hay una conexión a una red de cualquier tipo.

PPS The Above funciona en Ubuntu 12.04. Es posible que / sys no exista en algunas otras distribuciones. Vea abajo:

Las distribuciones modernas de Linux incluyen un directorio / sys como un sistema de archivos virtual (sysfs, comparable a / proc, que es un procfs), que almacena y permite la modificación de los dispositivos conectados al sistema, mientras que muchos sistemas operativos tradicionales UNIX y similares a Unix usan / sys como enlace simbólico al árbol de fuentes del kernel. [cita requerida]

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

Jesse
fuente
1
¡Cuidado ahora! " cat /sys/class/net/wwan0/carrierNo funciona en ubuntu 14.04 LTS.
dotnetCarpenter
1
Es posible que desee poner 2>/dev/nulldespués cat /sys/class/net/$interface/carrierpara no tener una salida de error en caso de que la red esté desactivada.
jarno
25

Esto funciona tanto en MacOSX como en Linux:

#!/bin/bash

ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline
legel
fuente
Excepto osx ( ping: invalid option -- w)
avishayp
fping google.como simplemente fping 8.8.8.8hace la magia con un bono, obtienes un código de estado sin la necesidad de probarlo (" google.com is alive") ...
Roger
9

En Bash, usando su envoltorio de red a través de / dev / { udp , tcp } / host / port :

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

( :es el no-op de Bash, porque solo desea probar la conexión, pero no el procesamiento).

Luchosteína
fuente
7

He escrito scripts antes de eso, simplemente use telnet para conectarse al puerto 80, luego transmita el texto:

HTTP/1.0 GET /index.html

seguido de dos secuencias CR / LF.

Siempre que obtenga algún tipo de respuesta HTTP, generalmente puede asumir que el sitio está funcionando.

paxdiablo
fuente
3
¿Por qué reinventar la rueda? curl y wget ambos hacen esto perfectamente.
Adam Rosenfield
6
Porque wget y curl no siempre están disponibles (por ejemplo, restricciones en entornos corporativos). Telnet ha sido una parte estándar de todos los UNIX desde el tiempo t = 0.
paxdiablo
Sí, el telnet ha sido una forma bastante estándar de probar conexiones durante bastante tiempo.
PTBNL
2
Buen punto, aunque wget es bastante común. Otra opción es netcat (nc), aunque en este caso no supone ninguna mejora respecto a telnet.
Adam Rosenfield
7

La respuesta principal pasa por alto el hecho de que puede tener una conexión perfectamente estable a su puerta de enlace predeterminada, pero eso no significa automáticamente que pueda acceder a algo en Internet. El OP pregunta cómo puede probar una conexión con el mundo. Por lo tanto, sugiero modificar la respuesta principal cambiando la IP de la puerta de enlace a una IP conocida (xyzw) que esté fuera de su LAN.

Entonces la respuesta sería:

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

También se eliminan las comillas inversas desfavorecidas para la sustitución de comandos [1] .

Si solo desea asegurarse de estar conectado al mundo antes de ejecutar algún código, también puede usar:

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

asegúrese de que su red permita la entrada y salida del tráfico TCP, luego podría recuperar su IP pública con el siguiente comando

curl ifconfig.co
WaiKit Kung
fuente
5

Ejecute el siguiente comando para verificar si un sitio web está activo y qué mensaje de estado muestra el servidor web:

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

El código de estado '200 OK' significa que la solicitud se ha realizado correctamente y se puede acceder a un sitio web.

Chaminda Bandara
fuente
2
Una mejor implementación podría sercurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Luca Galasso
4

Si su servidor de nombres local no funciona,

ping 4.2.2.1

es una IP siempre activa fácil de recordar (en realidad es un servidor de nombres, incluso).

efímero
fuente
5
ping 8.8.8.8 (Google NS)
usuario3439968
4

La respuesta más votada no funciona para MacOS, por lo que para aquellos en una Mac, he probado esto con éxito:

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

probado en MacOS High Sierra 10.12.6

Francisc0
fuente
2
Cambie el routecomando a route -n get default 2> /dev/null | grep gatewaypara evitar escribir un error en stderr cuando esté desconectado.
devstuff
4

Este script bash busca continuamente Internet y emite un pitido cuando Internet está disponible.

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

camino más corto: fping 4.2.2.1=> "4.2.2.1 está vivo"

prefiero esto porque es una salida más rápida y menos detallada ping, la desventaja es que tendrás que instalarlo.

puede utilizar cualquier DNS público en lugar de un sitio web específico.

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

-q devuelve un código de salida, por lo que solo estoy mostrando un ejemplo de cómo ejecutar algo en línea.

para instalar en Mac: brew install fping; en ubuntu:sudo apt-get install fping

Alex Moore-Niemi
fuente
2

Ping fue diseñado para hacer exactamente lo que busca hacer. Sin embargo, si el sitio bloquea el eco ICMP, siempre puede hacer el telnet al puerto 80 de algún sitio, wget o curl.

nikudesu
fuente
2

Verificar la página de índice de Google es otra forma de hacerlo:

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

De manera similar a la respuesta de @ Jesse , esta opción podría ser mucho más rápida que cualquier solución que use pingy quizás un poco más eficiente que la respuesta de @ Jesse .

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

Explicación:

Este comando se usa findcon -execpara ejecutar el comando en todos los archivos que no se nombran *lo*en/sys/class/net/ . Deben ser enlaces a directorios que contengan información sobre las interfaces de red disponibles en su máquina.

El comando que se ejecuta es un shcomando que verifica el contenido del archivo carrieren esos directorios. El valor de $interface/carriertiene 3 significados - Citando :

Parece que hay tres estados:

  • ./carrier no legible (por ejemplo, cuando la interfaz está deshabilitada en Network Manager).
  • ./carrier contiene "1" (cuando la interfaz está activada y está conectada a una red WiFi)
  • ./carrier contienen "0" (cuando la interfaz está activada y no está conectada a una red WiFi)

La primera opción no se atiende en la respuesta de @ Jesse . El shcomando rayado es:

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

catse utiliza para comprobar el contenido carriery redirigir toda la salida a la salida estándar incluso cuando falla porque el archivo no es legible. Si grep -qencuentra "1"entre esos archivos, significa que hay al menos 1 interfaz conectada. El código de salida de grep -qserá el código de salida final.

Uso

Por ejemplo, usando el estado de salida de este comando, puede usarlo para iniciar un gnubiff en su ~/.xprofilesolo si tiene una conexión a 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 &

Referencia

Doron Behar
fuente
1

Pong no significa que el servicio web en el servidor se esté ejecutando; simplemente significa que el servidor está respondiendo al eco ICMP. Recomendaría usar curl y verificar su valor de retorno.

tomoe
fuente
0

Si su objetivo es comprobar el acceso a Internet , muchas de las respuestas existentes a esta pregunta son erróneas. Algunas cosas que debe tener en cuenta:

  1. Es posible que su computadora esté conectada a una red sin que esa red tenga acceso a Internet
  2. Es posible que un servidor esté inactivo sin que todo Internet sea inaccesible
  3. Es posible que un portal cautivo devuelva una respuesta HTTP para una URL arbitraria incluso si no tiene acceso a Internet

Con eso en mente, creo que la mejor estrategia es contactar a varios sitios a través de una conexión HTTPS y devolver el valor verdadero si alguno de esos sitios responde.

Por ejemplo:

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

Algunas notas sobre este enfoque:

  1. Es robusto contra todos los falsos positivos y negativos que describí anteriormente.
  2. Todas las solicitudes ocurren en paralelo para maximizar la velocidad.
  3. Devolverá falso si técnicamente tiene acceso a Internet pero el DNS no es funcional o su configuración de red está desordenada, lo que creo que es algo razonable en la mayoría de los casos.
Ajedi32
fuente
No se está probando el código de retorno de curl. En mi sistema, si la red no está disponible, curl da rc = 6 (resolución de DNS fallida) pero este código aún informa "Conectado a Internet".
ceperman
@ceperman El código de retorno de curl se prueba en la línea donde dice if wait $pid;. No tengo idea de por qué eso no funciona en su sistema. ¿Estás seguro de que estás usando bash?
Ajedi32
@ceperman Otra posibilidad; tal vez una de las URL en la lista en la parte superior realmente le devuelva el éxito, aunque las otras no estén resolviendo el nombre.
Ajedi32
2
Mi bash es bastante básico, así que sigo leyendo waity ahora entiendo que el código de retorno se está probando. Volví a copiar tu código y hoy funciona. ¡Ups! Debo haber estropeado algo la última vez, aunque no puedo entender qué o cómo. Sin embargo, mea culpa. Disculpas
ceperman
-1

Esto es notablemente más rápido que cualquier solución publicada aquí y se puede utilizar para probar un host específico. .

El truco es resolver la IP utilizando un solucionador de DNS menos ocupado que el empleado por 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
fuente
2
Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden dejar de ser válidas si cambia la página enlazada. - De la opinión
David Buck
No se aplica a esta situación particular.
Alberto Salvia Novella