Como testar uma conexão à Internet com o bash?

113

Como uma conexão de internet pode ser testada sem pingar algum site? Quero dizer, e se houver uma conexão, mas o site estiver fora do ar? Existe uma verificação de conexão com o mundo?

Laurys
fonte
2
ping em vários sites diferentes?
1
mas não quero fazer ping em sites, não há outra opção?
lauriys de
6
Só quero ver que talvez haja outra maneira!
lauriys
2
Não há maneira melhor do que enviar e receber um único pacote para um conjunto de endereços que você sabe que não devem ficar off-line de uma vez. Outra maneira é verificar o DNS definido atual se não quiser que seu aplicativo execute um ping mais público domínio.
Tamara Wijsman
14
Quero saber se alguém está ouvindo, sem fazer barulho!
Kaz

Respostas:

131

Sem ping

#!/bin/bash

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

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

-q : modo de silêncio

--spider : não obtenha, apenas verifique a disponibilidade da página

$? : código de retorno do shell

0 : código shell "Tudo OK"

Sem 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
fonte
2
muito bom ... mas é claro que assume que a caixa tem wget. dispositivos embutidos e outros enfeites provavelmente não. ;)
Eric Sebasta
5
Tente isto: echo -e "GET google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968
1
tcping também seria útil aqui. (tcping www.yahoo.com 80) && echo "Site no ar"
David Ramirez
A instrução if / else usada aqui com explicação é ótima. Obrigado !
Danijel-James W
1
@ user3439968 Você precisa adicionar o tempo limite para nccertificar-se de que ele expire . algo comonc google.com 80 -w 10
kaptan de
93

Faça ping no seu gateway padrão:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error
mateusza
fonte
14
boa técnica, pode ser modificado para ser usado em uma função: function ping_gw() { ... && return 0 || return 1 }e então usado da seguinte maneira:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy
1
no mac os isso não funciona via copiar e colar: "-bash: ip: comando não encontrado ping: opção ilegal - w"
Benedikt S. Vogler
1
Dá um alarme falso se executado a partir de um convidado de virtualização enquanto o host não está conectado.
Teresa e Junior
1
Dá-me falsos negativos no sistema operacional elementar (0.4.1, Acer Aspire E 15)
Malcolm
1
Cuidado com isso. Acabei de testar isso ifconfig down wlan0e ainda tenho um gateway padrão com ping, embora eu não consiga acessar o mundo externo.
Bruno Bronosky
29

Super Obrigado ao usuário somedrew por sua postagem aqui: https://bbs.archlinux.org/viewtopic.php?id=55485 em 2008-09-20 02:09:48

Procurar em / sys / class / net deve ser uma maneira

Aqui está meu script para testar uma conexão de rede diferente do loopback. Eu uso o seguinte em outro script que tenho para testar periodicamente se meu site está acessível. Se NÃO estiver acessível, uma janela pop-up me alertará sobre um problema.

O script abaixo me impede de receber mensagens pop-up a cada cinco minutos sempre que meu laptop não está conectado à rede.

#!/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 aqueles que são novos no bash: A declaração final 'if' testa se NÃO [!] Online e sai se for o caso. Consulte man bash e pesquise "As expressões podem ser combinadas" para obter mais detalhes.

PS Eu sinto que o ping não é a melhor coisa a se usar aqui porque ele visa testar uma conexão com um determinado host, NÃO testar se há uma conexão com uma rede de qualquer tipo.

PPS The Above funciona no Ubuntu 12.04 O / sys pode não existir em algumas outras distros. Ver abaixo:

As distribuições modernas do Linux incluem um diretório / sys como um sistema de arquivos virtual (sysfs, comparável a / proc, que é um procfs), que armazena e permite a modificação dos dispositivos conectados ao sistema, enquanto muitos sistemas operacionais UNIX e Unix tradicionais usam / sys como um link simbólico para a árvore fonte do kernel. [carece de fontes?]

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

Jesse
fonte
1
Cuidado agora! " cat /sys/class/net/wwan0/carrierNão funciona no ubuntu 14.04 LTS.
dotnetCarpenter
1
Você pode querer colocar 2>/dev/nulldepois cat /sys/class/net/$interface/carrierpara não ter saída de erro caso a rede seja desabilitada.
jarno
25

Isso funciona em MacOSX e Linux:

#!/bin/bash

ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline
Legel
fonte
Exceto para osx ( ping: invalid option -- w)
avishayp de
fping google.comou simplesmente fping 8.8.8.8faz a mágica com um bônus, você obtém o código de status sem a necessidade de testá-lo (" google.com is alive") ...
Roger,
9

No Bash, usando seu wrapper de rede por meio de / dev / { udp , tcp } / host / port :

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

( :é o Bash no-op, porque você só quer testar a conexão, mas não o processamento.)

Luchostein
fonte
7

Já escrevi scripts antes disso, basta usar telnet para se conectar à porta 80 e, em seguida, transmitir o texto:

HTTP/1.0 GET /index.html

seguido por duas sequências CR / LF.

Desde que você obtenha algum tipo de resposta HTTP, geralmente pode-se presumir que o site está funcionando.

paxdiablo
fonte
3
Por que reinventar a roda? curl e wget fazem isso perfeitamente.
Adam Rosenfield
6
Porque wget e curl nem sempre estão disponíveis (por exemplo, restrições em ambientes corporativos). Telnet tem sido uma parte padrão de todo UNIX desde o tempo t = 0.
paxdiablo
Sim, o telnet tem sido uma forma padrão de testar conexões por um bom tempo.
PTBNL
2
Bom ponto, embora wget seja bastante comum. Outra opção é o netcat (nc), embora neste caso não seja nenhuma melhoria em relação ao telnet.
Adam Rosenfield
7

A principal resposta ignora o fato de que você pode ter uma conexão perfeitamente estável com seu gateway padrão, mas isso não significa automaticamente que você pode realmente acessar algo na Internet. O OP pergunta como ele / ela pode testar uma conexão com o mundo. Portanto, sugiro alterar a resposta principal mudando o IP do gateway para um IP conhecido (xyzw) que está fora de sua LAN.

Portanto, a resposta seria:

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

Também removendo os crases desfavoráveis ​​para substituição de comandos [1] .

Se você apenas deseja ter certeza de que está conectado ao mundo antes de executar algum código, também pode usar:

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

certifique-se de que sua rede permite a entrada e saída de tráfego TCP, então você poderá obter de volta seu IP público com o seguinte comando

curl ifconfig.co
WaiKit Kung
fonte
5

Execute o seguinte comando para verificar se um site está ativo e qual mensagem de status o servidor da web está mostrando:

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

O código de status '200 OK' significa que a solicitação foi bem-sucedida e um site está acessível.

Chaminda Bandara
fonte
2
Uma implementação melhor poderia sercurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Luca Galasso
4

Se o seu servidor de nomes local estiver inativo,

ping 4.2.2.1

é um IP sempre ativo fácil de lembrar (na verdade, é até mesmo um servidor de nomes).

efêmero
fonte
5
ping 8.8.8.8 (Google NS)
user3439968
4

A resposta mais votada não funciona para MacOS, então, para aqueles em um mac, testei com sucesso:

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

testado em MacOS High Sierra 10.12.6

Francisc0
fonte
2
Altere o routecomando para route -n get default 2> /dev/null | grep gatewaypara evitar a gravação de um erro em stderr quando estiver offline.
devstuff
4

Este script bash verifica continuamente a existência de Internet e emite um sinal sonoro quando a Internet está disponível.

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

caminho mais curto: fping 4.2.2.1=> "4.2.2.1 está vivo"

Eu prefiro isso porque é mais rápido e menos prolixo do que ping, a desvantagem é que você terá que instalá-lo.

você pode usar qualquer dns público em vez de um site específico.

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

-q retorna um código de saída, então estou apenas mostrando um exemplo de execução de algo que você está online.

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

Alex Moore-Niemi
fonte
2

O Ping foi projetado para fazer exatamente o que você deseja fazer. No entanto, se o site bloquear o eco ICMP, você sempre poderá fazer o telnet para a porta 80 de algum site, wget ou curl.

Nikudesu
fonte
2

Verificar a página de índice do Google é outra maneira de fazer isso:

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

De forma semelhante à resposta de @Jesse , esta opção pode ser muito mais rápida do que qualquer solução usando pinge talvez um pouco mais eficiente do que a resposta de @Jesse .

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

Explicação:

Este comando usa findcom -execpara executar o comando em todos os arquivos não nomeados *lo*em /sys/class/net/. Devem ser links para diretórios contendo informações sobre as interfaces de rede disponíveis em sua máquina.

O comando executado é um shcomando que verifica o conteúdo do arquivo carriernesses diretórios. O valor de $interface/carriertem 3 significados - Citação :

Parece que existem três estados:

  • ./carrier não legível (por exemplo, quando a interface está desabilitada no Network Manager).
  • ./carrier contém "1" (quando a interface está ativada e conectada a uma rede WiFi)
  • ./carrier contém "0" (quando a interface está ativada e não está conectada a uma rede WiFi)

A primeira opção não foi atendida na resposta de @Jesse . O shcomando distribuído é:

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

catestá sendo usado para verificar o conteúdo carriere redirecionar toda a saída para a saída padrão, mesmo quando falha porque o arquivo não é legível. Se grep -qencontrar "1"entre esses arquivos, significa que há pelo menos 1 interface conectada. O código de saída de grep -qserá o código de saída final.

Uso

Por exemplo, usando o status de saída desse comando, você pode usá-lo para iniciar um gnubiff no seu ~/.xprofilesomente se tiver uma conexão com 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 &

Referência

Doron Behar
fonte
1

Pong não significa que o serviço da web no servidor está em execução; significa apenas que o servidor está respondendo ao eco ICMP. Eu recomendaria usar curl e verificar seu valor de retorno.

tomoe
fonte
0

Se o seu objetivo é realmente verificar o acesso à Internet , muitas das respostas existentes para essa pergunta são erradas. Algumas coisas que você deve estar ciente:

  1. É possível que seu computador esteja conectado a uma rede sem que essa rede tenha acesso à Internet
  2. É possível que um servidor fique inativo sem que toda a Internet fique inacessível
  3. É possível que um portal cativo retorne uma resposta HTTP para um URL arbitrário, mesmo se você não tiver acesso à Internet

Com isso em mente, acredito que a melhor estratégia é entrar em contato com vários sites por meio de uma conexão HTTPS e retornar true se algum desses sites responder.

Por exemplo:

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

Algumas notas sobre esta abordagem:

  1. É robusto contra todos os falsos positivos e negativos que descrevi acima
  2. Todas as solicitações acontecem em paralelo para maximizar a velocidade
  3. Ele retornará falso se você tecnicamente tiver acesso à Internet, mas o DNS não estiver funcionando ou se suas configurações de rede estiverem bagunçadas, o que eu acho que é uma coisa razoável a se fazer na maioria dos casos
Ajedi32
fonte
O código de retorno do curl não está sendo testado. No meu sistema, se a rede não estiver disponível, o curl dá rc = 6 (resolução de DNS com falha), mas este código ainda informa "Conectado à Internet".
ceperman
@ceperman O código de retorno para curl é testado na linha onde diz if wait $pid;. Não faço ideia por que isso não está funcionando em seu sistema. Tem certeza de que está usando o bash?
Ajedi32
@ceperman Outra possibilidade; talvez uma das URLs na lista no topo realmente faz sucesso retorno para você, mesmo que os outros estão fracassando resolução de nomes?
Ajedi32
2
Meu bash é muito básico, então continuei lendo waite agora entendo que o código de retorno está realmente sendo testado. Copiei novamente o seu código e hoje funciona - opa! Devo ter bagunçado alguma coisa da última vez, embora não consiga entender o quê ou como. No entanto, mea culpa. Desculpas.
ceperman
-1

Isso é notavelmente mais rápido que qualquer solução postada aqui e também pode ser usado para testar um host específico .

O truque é resolver o IP usando um solucionador de DNS menos ocupado do que aquele empregado 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
fonte
2
Embora este link possa responder à pergunta, é melhor incluir as partes essenciais da resposta aqui e fornecer o link para referência. As respostas somente com link podem se tornar inválidas se a página vinculada mudar. - Da avaliação
David Buck
Não se aplica a esta situação particular.
Alberto Salvia Novella