en attente de réseau dans un script bash

9

J'exécute un script qui repose sur le réseau en cours et un partage réseau monté. Le script s'exécute lors de la connexion (ce qui se produit automatiquement après le démarrage). Le problème est qu'au moment où le script s'exécute, je n'ai généralement pas encore d'adresse IP (DHCP). Pour le moment, je dors simplement le script pendant 15 secondes, mais je n'aime pas du tout cette approche, car je veux pouvoir dire à l'utilisateur si quelque chose ne va pas.

Mon plan est de boucler alors que je n'ai pas encore d'adresse IP et de continuer quand je le fais. Surtout, il doit expirer après un certain temps. Ce que j'ai if [ ifconfig | grep "192.168.100" ];imaginé, c'est de mais ce qui se passe, c'est que grep consomme le ];et ne l'aime pas. Ensuite, bash est également contrarié, car il ne peut pas trouver le ];grep mangé. Et puis je n'ai même pas mis en œuvre le délai d'attente.

Quelqu'un a suggéré de conserver une variable et de dormir, disons, une seconde à chaque itération et d'augmenter cette variable à chaque fois. Voici mon script complet (ne fonctionne pas) (je suis assez nouveau dans le script bash):

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...

Tout pointeur dans la bonne direction serait grandement apprécié!

aguywithsocks
la source
1
Si votre init est systemd, écrivez un fichier de service qui attend network-online.target...
jasonwryan
pas besoin de rediriger la grepsortie vers /dev/null. Utilisez -qplutôt l'option. Et aussi je ne pense pas que le fait de saluer ifconfig soit une bonne idée. Pourquoi ne pas utiliser à la pingplace?
précipiter le
pingpeut échouer en fonction du réseau en question. Il est préférable de simplement vérifier la configuration de fonctionnement du système.
Bratchley

Réponses:

8

Syntaxe du shell

Vous semblez confus concernant les conditions dans les scripts shell. Chaque commande shell a un état de sortie, qui est un entier compris entre 0 et 255, 0 signifiant succès et toute autre valeur signifiant échec. Des instructions telles que ifet whilequi attendent des opérandes booléens inspectent l'état de sortie de la commande et traitent 0 (succès) comme vrai et toute autre valeur (échec) comme fausse.

Par exemple, la grepcommande renvoie 0 si le modèle est trouvé et 1 si le modèle n'est pas trouvé. Donc

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

répète la boucle tant que le motif 192.168.100.se trouve dans la sortie de ifconfig. Notez que le modèle 192.168.100.correspond à des chaînes comme 192x168 1007, car .dans une expression régulière correspond à n'importe quel caractère; pour rechercher une chaîne littérale, passez l'option -Fà grep. Pour inverser la condition, mettez !en avant.

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

Plus loin dans le script, vous souhaitez comparer la valeur d'une variable à un nombre. Vous utilisez l' -gtopérateur, qui fait partie de la syntaxe des expressions conditionnelles comprises par la testcommande. La testcommande renvoie 0 si l'expression conditionnelle est vraie et 1 si l'expression conditionnelle est fausse.

if test "$x" -gt 200; then

Il est habituel d'utiliser l'autre nom [pour la testcommande. Ce nom s'attend à ce que la commande se termine avec le paramètre ]. Les deux façons d'écrire cette commande sont exactement équivalentes.

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

Bash propose également une troisième façon d'écrire cette commande, avec la syntaxe spéciale [[ … ]]. Cette syntaxe spéciale peut prendre en charge quelques opérateurs de plus que [, car [est une commande ordinaire soumise aux règles d'analyse habituelles, alors qu'elle [[ … ]]fait partie de la syntaxe du shell.

Encore une fois, gardez à l' esprit que [est pour les expressions conditionnelles , qui sont une syntaxe avec des opérateurs tels que -n, -gt... [ne signifie pas « valeur booléenne »: (état de sortie = 0) toute commande a une valeur booléenne.

Détecter que le réseau est actif

Votre façon de détecter que le réseau est en place n'est pas robuste. Notez en particulier que votre script sera déclenché dès qu'une interface réseau acquiert une adresse IP dans la plage spécifiée. En particulier, il est fort possible que DNS ne soit pas encore opérationnel à ce stade, sans parler des partages réseau montés.

Avez-vous vraiment besoin d'exécuter ces commandes lorsque quelqu'un se connecte? Il est plus facile d'exécuter une commande automatiquement lorsque le réseau est activé. La façon de procéder dépend de votre distribution et de votre utilisation de NetworkManager.

Si vous devez exécuter ces commandes dans le cadre des scripts de connexion, testez la ressource dont vous avez vraiment besoin, pas la présence d'une adresse IP. Par exemple, si vous souhaitez tester s'il /net/somenode/somedirest monté, utilisez

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

Si vous avez un débutant ou un système…

alors vous pouvez l'utiliser. Par exemple, avec Upstart , marquez votre travail comme start on net-device-up eth0(remplacez eth0par le nom de l'interface qui fournit la connectivité réseau souhaitée). Avec Systemd, voir Provoquer l'exécution d'un script après le démarrage de la mise en réseau?

Gilles 'SO- arrête d'être méchant'
la source
Je suppose que ça /net/devrait l'être /proc/net?
sebix
@sebix Non, pourquoi le ferait-il? Je ne parle pas de la configuration réseau de Linux. Je donne un exemple de point de montage pour un système de fichiers distant, /netest un emplacement commun pour ces points de montage.
Gilles 'SO- arrête d'être méchant'
Ok, vous avez donc besoin d'un lecteur réseau monté. Existe-t-il également une solution plus générique?
sebix
@sebix Une solution pour quoi? Exiger un lecteur réseau monté était un exemple d'objectif, pas un exemple de solution.
Gilles 'SO- arrête d'être méchant'
1

Il suffit de compter la sortie de ip add showPar exemple:

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

Ensuite, vous pouvez simplement créer une branche sur le nombre de lignes retournées, le cas échéant. Vous auriez probablement juste vérifier si c'était zéro, et si oui, dormez et répétez la boucle.

Code non testé pour l'illustration:

while [ 1 ]; do

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

  sleep 1

done
Bratchley
la source
1

Ping renverra une réponse 0 si au moins une tentative a réussi. Vous pouvez envisager d'envoyer une requête ping au serveur auquel vous vous connectez jusqu'à ce qu'il réussisse.

brwtx
la source