Loop de ping contínuo no script

2

Estou trabalhando em alguma compilação personalizada do Openwrt. Alguns dos meus scripts fazem ping para testar a conexão antes de fazer suas coisas.

if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
  do stuff;
else
 echo "no connection"
fi

Alguns deles executam outros e, como ping leva algum tempo, a execução de scripts leva mais tempo do que deveria, o que é um problema em alguns casos.

Eu gostaria de fazer algum tipo de loop contínuo que escreve 0 ou 1 em algum arquivo. De agora em diante, scripts que usam ping para teste de conexão testarão o que está em somefile .

Existe uma maneira de escrever esse roteiro?

    
por 180doman 19.07.2018 / 12:34

3 respostas

9

Você quer dizer algo tão simples assim:

while :; do
   ping -c 1 -w 3 8.8.8.8; echo $? > /tmp/ping.status
   sleep 1
done

Isso gravará o status de saída de ping a /tmp/ping.status uma vez por segundo. Então, em outro script, você poderia ter algo como:

pingFailed=$(cat /tmp/ping.status)
if [ $pingFailed -ne 0 ]; then
    echo "No connection"
else
    echo "Connected!"
fi

Então, sim, você poderia fazer isso. No entanto, é um método muito ruim de verificar sua conexão. Obviamente, existem condições de corrida aqui. Que a conexão estava ativa quando o primeiro loop foi executado, não significa que ele esteja ativo neste segundo. Mais importante, se você ler o arquivo ping.status no início do script, isso não significa que a conexão ainda estará lá no final do script. Além disso, você está enviando spam tanto para sua rede quanto para sua CPU com solicitações contínuas. Isso realmente não é muito elegante.

Uma forma mais rápida e simples de testar se sua conexão está ativa (pelo menos no Linux) está olhando para /sys/class/net/$NIC/link_mode onde $NIC é o nome da sua placa de rede. Por exemplo, no meu sistema:

## Wireless connection up
$ cat /sys/class/net/wlp3s0/link_mode 
1
## Wireless connection down
$ cat /sys/class/net/wlp3s0/link_mode 
0

Você pode escrever uma função que verifique isso:

isLinkDown(){
    return $(cat /sys/class/net/wlp3s0/link_mode)
}

E você pode usá-lo em seus scripts assim:

if isLinkDown; then 
    echo Link Down
else
    echo Link Up
    
por 19.07.2018 / 12:52
3

A resposta de Terdon é boa, mas eu evitaria o inchaço da rede,

mas primeiro um aparte ; ping pode levar de 0.002s a 8.8.8.8, portanto, se você quiser testar uma rede de baixa latência,

$ timeout 0.1 ping -c 1 8.8.8.8

pode ser usado para garantir 1/10 de um segundo tempo de teste (porque o ping não tem tempos de espera abaixo do segundo).

Agora, a answer otimiza a velocidade e o uso da rede; você deve fazer seus scripts passarem parâmetros;

#!/bin/bash

usage() {
    echo "Usage: $0 [OPTIONS]"
    echo " OPTIONS:"
    echo "  -h     this Help message"
    echo "  -n     do Not re-test network connectivity"
}

NO_TEST=false
while getopts "nh" OPT; do
    case "$OPT" in
        n)
            NO_TEST=true
            ;;
        h)
            usage
            exit 0
            ;;
        *)
            echo "unsupported option $OPT" >&2
            usage
            exit 1
            ;;
    esac
done
shift $((OPTIND - 1))

if ! $NO_TEST && ! ping -c 1 -w 3 8.8.8.8; then
    echo "no connection" >&2
    exit 2
fi
echo "do stuff";
    
por 19.07.2018 / 12:56
0

Obrigado a todos por todas as respostas! Eu só preciso de algum tempo para levar alguns dos seus valiosos pensamentos em consideração. Para esclarecer algumas coisas, só quero acrescentar que: 1. Não consigo usar parâmetros, pois a maioria desses scripts funciona no init.d ou é executada pelo cron.
2. A idéia toda está sendo criada principalmente para conexão de modem. E as latências de ping dependem da força do sinal. Eu nem tenho certeza se posso diminuir o intervalo de verificação de ping além de 1s para ter verificações confiáveis quando a intensidade do sinal é baixa, mas a conexão ainda existe. Isso porque eu pensei que o loop de ping com o intervalo padrão, que apenas resulta em algum lugar facilmente acessível, seria o melhor compromisso.

Isso é o que eu usei recentemente

modemup(){
    echo -e "AT+QRST=1,0\r\n" > /dev/ttyUSB2
    ifdown $INTERFACE && ifup $INTERFACE

    if [ "$(ifconfig | grep $INTFC_NAME)" ]; then
        return 0
    else
        echo "Cant start modem interface"
        return 1
    fi
  } 

reconnect(){
    MAX_ATTEMPTS=$1 #number of tries before reboot
    TRIES=1

    while [ $TRIES -le $MAX_ATTEMPTS ]; do
        echo "Trying to reconnect ..."
        echo "Number of try: $TRIES"
        modemup
        /etc/init.d/network restart
        sleep 10
        if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
            break
        fi
        : $((TRIES+=1))
    done
    echo "Tried $MAX_ATTEMPTS times, couldnt reconnect. Rebooting ..."
    reboot
}

while true; do
    if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
         rm -rf $NOCONFILE #if noconnection file exists delete it
    else
        mkdir -p $LOG_DIR/${DAY_DIR}
        TIME='date +%Y%m%d%H%M%S'
        echo "$TIME: Connection lost" 2>&1 | tee -a $LOG_FILE
        touch $NOCONFILE
        reconnect $ATTEMPTS 2>&1 | tee -a $LOG_FILE   
    fi
    sleep $INTERVAL
done
    
por 19.07.2018 / 16:33