Como pingar no linux até que o host seja conhecido?

43

Como posso pingar um determinado endereço e, quando encontrado, parar o ping.

Eu quero usá-lo em um script bash, então quando o host está iniciando, o script continua pingando e a partir do momento que o host estiver disponível, o script continua ...

    
por Sander Versluys 17.07.2009 / 09:45

12 respostas

78

Uma simplificação adicional da resposta de Martynas:

until ping -c1 www.google.com &>/dev/null; do :; done

observe que o próprio ping é usado como o teste de loop; assim que for bem sucedido, o loop termina. O corpo do loop está vazio, com o comando nulo " : " usado para evitar um erro de sintaxe.

Update: Eu pensei em uma maneira de fazer o Control-C sair do loop de ping de forma limpa. Isso executará o loop em segundo plano, interceptará o sinal de interrupção (Control-C) e eliminará o loop de segundo plano se ocorrer:

ping_cancelled=false    # Keep track of whether the loop was cancelled, or succeeded
until ping -c1 "$1" &>/dev/null; do :; done &    # The "&" backgrounds it
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Wait for the loop to exit, one way or another
trap - SIGINT    # Remove the trap, now we're done with it
echo "Done pinging, cancelled=$ping_cancelled"

É um pouco tortuoso, mas se você quiser que o loop seja cancelável, ele deve fazer o truque.

    
por 18.07.2009 / 01:16
22

Você pode fazer um loop, enviar um ping e dependendo do status quebrar o loop, por exemplo (bash):

while true; do ping -c1 www.google.com > /dev/null && break; done

Colocar isso em algum lugar do script será bloqueado até que www.google.com seja pingável.

    
por 17.07.2009 / 10:01
17

Sei que a pergunta é antiga ... e pergunta especificamente sobre ping , mas queria compartilhar minha solução.

Eu uso isso quando reiniciando hosts para saber quando posso SSH de volta para eles novamente. (Como ping responderá por vários segundos antes que sshd seja iniciado.)

until nc -vzw 2 $host 22; do sleep 2; done
    
por 11.10.2013 / 16:37
11

Efetue ping no host de destino uma vez. Verifique se o ping foi bem-sucedido (o valor de retorno do ping é zero). Se o host não estiver ativo, execute ping novamente.

O código a seguir pode ser salvo como um arquivo e chamado com o nome do host como argumento ou despojado da primeira e última linha e usado como função dentro de um script existente (nome do host waitForHost).

O código não avalia a causa da falha se o ping não resultar em uma resposta, fazendo um loop para sempre se o host não existir. Minha manpage BSD lista o significado de cada valor de retorno, enquanto o linux não, então eu acho que isso pode não ser portátil, é por isso que eu deixei de fora.

#!/bin/bash

PING='which ping'

function waitForHost
{
    if [ -n "$1" ]; 
    then
        waitForHost1 $1;
    else
        echo "waitForHost: Hostname argument expected"
    fi
}

function waitForHost1
{
    reachable=0;
    while [ $reachable -eq 0 ];
    do
    $PING -q -c 1 $1
    if [ "$?" -eq 0 ];
    then
        reachable=1
    fi
    done
    sleep 5
}
waitForHost $1
    
por 17.07.2009 / 09:58
9
UNREACHEABLE=1;
while [ $UNREACHEABLE -ne "0" ]; 
   do ping -q -c 1 HOST &> /dev/null; UNREACHEABLE=$?; sleep 1;
done

Você pode remover o sleep 1, ele está aqui apenas para evitar qualquer problema de inundação no caso de o host ser acessado, mas o ping não sairá com o código 0.

    
por 17.07.2009 / 10:09
4

Por favor, veja boas opções em stackoverflow . Aqui está um exemplo no bash, você terá que percorrer o código a seguir até retornar um resultado de ping bem-sucedido.


ping -c 1 -t 1 192.168.1.1;
if [ $? -eq 0 ]; then
    echo "192.168.1.1 is up";
else 
    echo "ip is down";
fi

    
por 17.07.2009 / 10:00
3

qualquer um dos loops acima também pode ser usado com fping em vez de ping, o que, IMO, é mais adequado para uso em scripts do que o próprio ping. Veja fping (1) para detalhes.

while ! fping -q $HOSTNAMES ; do :; done

também é útil para testar se as máquinas estão ativas antes de fazer algo nelas. Um exemplo simples:

for h in HOST1 HOST2 HOST3 ; do
  if fping -q $h ; then
     echo -n "$h : "
     ssh $h "uname -a"
  fi
done
    
por 19.07.2009 / 01:25
1

Isso tentará um determinado número de vezes.

t=4; c=0; r=0; until ping -c 1 hostname.com >/dev/null 2>&1 || ((++c >= t)); do r=$?; done; echo $r

Em vez de fazer eco de $r , você pode testá-lo e agir de acordo com seu valor:

if ((r)); then echo 'Failed to contact host'; else echo 'Continuing with script'; fi
    
por 26.06.2013 / 04:06
1

Para lidar bem com o SIGINT no ping BSD.

HOST=google.com NO=1; while [ $NO -ne 0 ]; do ping -W1 -c1 $HOST &>/dev/null; NO=$?;echo "$(date) ($HOST) $NO" ; done; echo "$(date) ($HOST) reachable"

como uma função

ping_until(){
  local NO=1
  while [ $NO -ne 0 ]; do
    ping -W1 -c1 $1 &>/dev/null; NO=$?
    # Optionally block ICMP flooding
    # sleep 1
    echo "$(date) ($1) ($NO)"
  done
}
    
por 31.03.2017 / 21:24
0

Eu tenho usado a seguinte função. Eu gosto porque posso dizer para parar de tentar depois de um tempo:

#!/usr/bin/env bash

function networkup {
  # Initialize number of attempts
  reachable=$1
  while [ $reachable -ne 0 ]; do
    # Ping supplied host
    ping -q -c 1 -W 1 "$2" > /dev/null 2>&1
    # Check return code
    if [ $? -eq 0 ]; then
      # Success, we can exit with the right return code
      echo 0
      return
    fi
    # Network down, decrement counter and try again
    let reachable-=1
    # Sleep for one second
    sleep 1
  done
  # Network down, number of attempts exhausted, quiting
  echo 1
}

Pode ser usado assim para lançar algo:

# Start-up a web browser, if network is up
if [ $(networkup 60 www.google.com) -eq 0 ]; then
  firefox &
fi
    
por 25.06.2013 / 20:30
0

Em geral, quero esperar que meu banco de dados ou outro servidor apareça, mas não quero esperar também por muito tempo. O código a seguir aguarda 10 segundos e, em seguida, define o código de saída se o servidor não aparecer dentro do limite de tempo.

Se o servidor aparecer antes do limite de tempo, o loop será curto-circuitado para que o próximo código possa ser executado.

for i in 'seq 1 10'; do date ; sleep 1 ; ping -c1 ${HOST} &>/dev/null && break ; done
    
por 09.08.2016 / 00:37
0

Um novo aprimoramento da resposta de Gordon Davisson:

until $(ping -c1 www.google.com &>/dev/null); do :; done

com o '$ ()' ao redor, um subshell é iniciado e, portanto, você pode usar o Control-C para finalizar o loop, caso o host não fique disponível.

    
por 23.07.2017 / 02:17