esperando pela rede em um script bash

8

Estou executando um script que depende da rede e de um compartilhamento de rede ser montado. O script é executado no login (o que acontece automaticamente após a inicialização). O problema é que, no momento em que o script é executado, normalmente ainda não tenho um endereço IP (DHCP). No momento eu durmo o roteiro por 15s, mas eu não gosto dessa abordagem, já que eu quero ser capaz de dizer ao usuário se algo está errado.

Qual é o meu plano, é loop enquanto ainda não tenho um endereço IP e continuo quando o faço. Crucialmente, tem que expirar depois de um tempo. O que eu descobri é if [ ifconfig | grep "192.168.100" ]; , mas o que acontece é que o grep consome ]; e não gosta disso. Então o bash também fica chateado, porque não consegue encontrar o ]; que o grep comeu. E então eu nem implementei o tempo limite.

Alguém sugeriu manter uma variável e dormir por, digamos, um segundo em cada iteração e aumentar essa variável a cada vez. Aqui está o meu script completo (não funciona) (sou relativamente novo no bash scripting):

x=0
while [ ifconfig | grep "192.168.100." > /dev/null ]; do
    echo "no nework"
    if "$x" -gt 200; then
        #Time out here
        exit 1
    x=$((x+1))
    sleep .1
    fi
done

#continue with rest of script...

Qualquer ponteiro na direção correta seria muito apreciado!

    
por aguywithsocks 28.07.2014 / 19:18

3 respostas

7

Sintaxe da shell

Você parece estar confuso em relação a condicionais em scripts de shell. Cada comando do shell possui um status de saída, que é um inteiro entre 0 e 255, com 0 significando sucesso e qualquer outro valor significando falha. Declarações como if e while que espera operandos booleanos inspecionar o status de saída do comando e tratar 0 (sucesso) como verdadeiro e qualquer outro valor (falha) como falsa.

Por exemplo, o comando grep retorna 0 se o padrão for encontrado e 1 se o padrão não for encontrado. Então

while ifconfig | grep "192.168.100." > /dev/null; do …

repete o loop, desde que o padrão 192.168.100. seja encontrado na saída de ifconfig . Observe que o padrão 192.168.100. corresponde a strings como 192x168 1007 , porque . em uma expressão regular corresponde a qualquer caractere; para procurar uma string literal, passe a opção -F para grep . Para inverter a condição, coloque ! na frente.

while ! ifconfig | grep -F "192.168.100." > /dev/null; do …

Além disso, no script, você quer comparar o valor de uma variável com um número. Você usa o operador -gt , que faz parte da sintaxe do condicional expressões compreendidas pelo comando test . O comando test retornará 0 se a expressão condicional for verdadeira e 1 se a expressão condicional for falsa.

if test "$x" -gt 200; then

É costume usar o nome alternativo [ para o comando test . Esse nome espera que o comando termine com o parâmetro ] . As duas formas de escrever este comando são exatamente equivalentes.

if [ "$x" -gt 200 ]; then

O Bash também oferece uma terceira maneira de escrever este comando, com a sintaxe especial [[ … ]] . Essa sintaxe especial pode suportar mais algumas operadoras do que [ , porque [ é um comando comum sujeito às regras comuns de análise, enquanto [[ … ]] faz parte da sintaxe da shell.

Novamente, lembre-se de que [ é para expressões condicionais , que são uma sintaxe com operadores como -n , -gt ,… [ não significa “valor booleano ": Qualquer comando tem um valor booleano (status de saída = 0?).

Detectando que a rede está ativa

Sua maneira de detectar que a rede está ativa não é robusta. Em particular, observe que seu script será acionado assim que qualquer interface de rede adquire um endereço IP dentro do intervalo especificado. Em particular, é bem possível que o DNS não esteja ativo até esse momento, e muito menos quaisquer compartilhamentos de rede montados.

Você realmente precisa executar esses comandos quando alguém faz login? É mais fácil executar um comando automaticamente quando a rede é ativada. A maneira de fazer isso depende da sua distribuição e se você usa o NetworkManager.

Se você precisar executar esses comandos como parte dos scripts de login, teste o recurso que realmente precisa, não a presença de um endereço IP. Por exemplo, se você quiser testar se /net/somenode/somedir está montado, use

while ! grep -q /net/somenode/somedir </proc/mounts; do
  sleep 1
done

Se você tem upstart ou systemd…

então você pode usá-lo. Por exemplo, com o Upstart , marque seu trabalho como start on net-device-up eth0 (substitua eth0 pelo nome da interface que fornece a conectividade de rede desejada). Com o Systemd, consulte Porque um script para executar após a rede ter começou?

    
por 29.07.2014 / 03:39
1

Apenas conte a saída de ip add show Por exemplo:

root@xxxxxxlp01 ~ $ ip add sh dev eth3 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth1 | grep inet
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet
    inet xxx.xxx.64.91/24 brd xxx.xxx.95.255 scope global eth0
    inet6 fe80::224:e8ff:fe78:4dfb/64 scope link
root@xxxxxxlp01 ~ $ ip add sh dev eth0 | grep inet | wc -l
2

Então você pode apenas ramificar no número de linha retornado conforme apropriado. Você provavelmente só iria verificar se era zero e, em caso afirmativo, dormir e repetir o loop.

Código não testado para ilustração:

while [ 1 ]; do

  if [ $(ip add sh dev eth0 | grep inet | wc -l) -ne 0 ]; then
     break
  fi

  sleep 1

done
    
por 28.07.2014 / 19:58
1

Ping retornará uma resposta 0 se pelo menos uma tentativa for bem-sucedida. Você pode considerar o ping do servidor ao qual está se conectando até que seja bem-sucedido.

    
por 28.07.2014 / 20:11