aguardando rede em um script bash

9

Estou executando um script que depende da instalação da rede e de um compartilhamento de rede 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, geralmente eu ainda não tenho um endereço IP (DHCP). No momento, durmo o script por 15 anos, mas não gosto dessa abordagem, pois quero poder dizer ao usuário se algo está errado.

Qual é o meu plano é fazer um loop enquanto eu ainda não tenho um endereço IP e continuar quando tiver. Crucialmente, ele deve expirar após um tempo. O que eu vim com é, if [ ifconfig | grep "192.168.100" ];mas o que acontece é que o grep consome ];e não gosta. Então o bash também fica chateado, porque não consegue encontrar o ];que 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 (que não funciona) (eu sou bastante 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 indicação na direção certa seria muito apreciada!

aguywithsocks
fonte
1
Se o seu init é systemd, escrever um arquivo de serviço que aguarda network-online.target...
jasonwryan
não há necessidade de redirecionar a grepsaída para /dev/null. Use a -qopção. E também não estou pensando em se o ifconfig é uma boa idéia. Por que não usar ping?
apressar
pingpode falhar dependendo da rede em questão. É melhor apenas verificar a configuração de execução do sistema.
Bratchley 28/07

Respostas:

8

Sintaxe do shell

Você parece estar confuso com relação às condicionais nos scripts de shell. Todo comando shell possui um status de saída, que é um número inteiro entre 0 e 255, com 0 significando sucesso e qualquer outro valor significando falha. Declarações como ife whileque esperam operandos booleanos inspecionam o status de saída do comando e tratam 0 (sucesso) como verdadeiro e qualquer outro valor (falha) como falso.

Por exemplo, o grepcomando retornará 0 se o padrão for encontrado e 1 se o padrão não for encontrado. assim

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 seqüências de caracteres como 192x168 1007, porque .em uma expressão regular corresponde a qualquer caractere; Para procurar uma string literal, passe a opção -Fpara 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ê deseja comparar o valor de uma variável com um número. Você usa o -gtoperador, que faz parte da sintaxe das expressões condicionais compreendidas pelo testcomando. O testcomando retornará 0 se a expressão condicional for verdadeira e 1 se a expressão condicional for falsa.

if test "$x" -gt 200; then

É habitual usar o nome alternativo [para o testcomando. Este nome espera que o comando para terminar com o parâmetro ]. As duas maneiras 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 operadores do que [, porque [é um comando comum sujeito às regras de análise usuais, enquanto [[ … ]]faz parte da sintaxe do shell.

Novamente, lembre-se de que [é para expressões condicionais , que são uma sintaxe para 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 adquirir um endereço IP dentro do intervalo especificado. Em particular, é bem possível que o DNS ainda não esteja ativo nesse momento, sem falar nos compartilhamentos de rede montados.

Você realmente precisa executar esses comandos quando alguém fizer login? É mais fácil executar um comando automaticamente quando a rede é criada. 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 logon, 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/somedirestá montado, use

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

Se você tem iniciante ou systemd…

então você pode usá-lo. Por exemplo, com o Upstart , marque seu trabalho como start on net-device-up eth0(substitua eth0pelo nome da interface que fornece a conectividade de rede desejada). Com o Systemd, consulte Causar a execução de um script após o início da rede?

Gilles 'SO- parar de ser mau'
fonte
Eu acho que /net/deveria ser /proc/net?
sebix
@sebix Não, por que? Não estou falando da configuração de rede do Linux. Estou dando um exemplo de um ponto de montagem para um sistema de arquivos remoto, /neté um local comum para esses pontos de montagem.
Gilles 'SO- stop be evil' em
Ok, então você precisa de uma unidade de rede montada. Também existe uma solução mais genérica?
sebix
@sebix Uma solução para quê? Exigir uma unidade de rede montada foi um exemplo de uma meta, não um exemplo de solução.
Gilles 'SO- stop being evil
1

Apenas conte a saída de ip add showPor 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

Em seguida, você pode apenas ramificar o número de linhas retornadas conforme apropriado. Você provavelmente verificaria se era zero e, se for o caso, durma e repita o ciclo.

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
Bratchley
fonte
1

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

brwtx
fonte