Warten auf Netzwerk in einem Bash-Skript

9

Ich führe ein Skript aus, das davon abhängt, dass das Netzwerk aktiv ist und eine Netzwerkfreigabe bereitgestellt wird. Das Skript wird bei der Anmeldung ausgeführt (was automatisch nach dem Start erfolgt). Das Problem ist, dass ich zum Zeitpunkt der Ausführung des Skripts normalerweise noch keine IP-Adresse (DHCP) habe. Im Moment schlafe ich das Skript nur für 15 Sekunden, aber ich mag diesen Ansatz überhaupt nicht, da ich dem Benutzer mitteilen möchte, ob etwas nicht stimmt.

Was ich vorhabe, ist eine Schleife, während ich noch keine IP-Adresse habe, und dann fortzufahren. Entscheidend ist, dass es nach einer Weile eine Auszeit geben muss. Was ich mir if [ ifconfig | grep "192.168.100" ];ausgedacht habe ist, aber was passiert ist, dass grepconsumes das ];und es nicht mag. Dann wird Bash auch wütend, weil es nicht findet, ];welcher Grep gegessen hat. Und dann habe ich das Timeout noch nicht einmal implementiert.

Jemand schlug vor, eine Variable beizubehalten und beispielsweise in jeder Iteration eine Sekunde zu schlafen und diese Variable jedes Mal zu erhöhen. Hier ist mein vollständiges (nicht funktionierendes) Skript (ich bin ziemlich neu im 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...

Alle Hinweise in die richtige Richtung wäre sehr dankbar!

aguywithsocks
quelle
1
Wenn Ihr Init systemd ist, schreiben Sie eine Servicedatei, die auf network-online.target... wartet
Jasonwryan
Die grepAusgabe muss nicht umgeleitet werden /dev/null. Verwenden Sie -qstattdessen die Option. Und ich finde es auch nicht gut, wenn ifconfig eine gute Idee ist. Warum nicht pingstattdessen verwenden?
Eile
pingkann je nach Netzwerk fehlschlagen. Es ist besser, nur die laufende Konfiguration des Systems zu überprüfen.
Bratchley

Antworten:

8

Shell-Syntax

Sie scheinen hinsichtlich der Bedingungen in Shell-Skripten verwirrt zu sein. Jeder Shell-Befehl hat einen Exit-Status, der eine Ganzzahl zwischen 0 und 255 ist, wobei 0 Erfolg und jeder andere Wert Fehler bedeutet. Anweisungen wie ifund while, die boolesche Operanden erwarten, überprüfen den Exit-Status des Befehls und behandeln 0 (Erfolg) als wahr und jeden anderen Wert (Fehler) als falsch.

Beispielsweise gibt der grepBefehl 0 zurück, wenn das Muster gefunden wird, und 1, wenn das Muster nicht gefunden wird. Damit

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

wiederholt die Schleife, solange das Muster 192.168.100.in der Ausgabe von gefunden wird ifconfig. Beachten Sie, dass das Muster 192.168.100.mit Zeichenfolgen wie übereinstimmt 192x168 1007, da .in einem regulären Ausdruck ein beliebiges Zeichen übereinstimmt. Übergeben Sie die Option -Fan , um nach einer Literalzeichenfolge zu suchen grep. Um den Zustand umzukehren, stellen Sie ihn !vor.

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

Weiter im Skript möchten Sie den Wert einer Variablen mit einer Zahl vergleichen. Sie verwenden den -gtOperator, der Teil der Syntax der vom Befehl verstandenen bedingten Ausdrücke isttest . Der testBefehl gibt 0 zurück, wenn der bedingte Ausdruck wahr ist, und 1, wenn der bedingte Ausdruck falsch ist.

if test "$x" -gt 200; then

Es ist üblich, den alternativen Namen [für den testBefehl zu verwenden. Dieser Name erwartet, dass der Befehl mit dem Parameter endet ]. Die beiden Schreibweisen dieses Befehls sind genau gleichwertig.

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

Bash bietet auch eine dritte Möglichkeit, diesen Befehl mit der speziellen Syntax zu schreiben [[ … ]]. Diese spezielle Syntax kann einige Operatoren mehr unterstützen als [, da [ein gewöhnlicher Befehl den üblichen Parsing-Regeln [[ … ]]unterliegt und Teil der Shell-Syntax ist.

Auch bedenken Sie, dass [für ist bedingte Ausdrücke , die eine Syntax mit Operatoren wie ist -n, -gt... [bedeutet nicht „boolean value“: (Exit - Status = 0) jeder Befehl einen Booleschen Wert hat.

Erkennen, dass das Netzwerk aktiv ist

Ihre Methode zum Erkennen, dass das Netzwerk aktiv ist, ist nicht robust. Beachten Sie insbesondere, dass Ihr Skript ausgelöst wird, sobald eine Netzwerkschnittstelle eine IP-Adresse innerhalb des angegebenen Bereichs erhält. Insbesondere ist es durchaus möglich, dass DNS zu diesem Zeitpunkt noch nicht aktiv ist, geschweige denn, dass Netzwerkfreigaben bereitgestellt werden.

Müssen Sie diese Befehle wirklich ausführen, wenn sich jemand anmeldet? Es ist einfacher, einen Befehl automatisch auszuführen, wenn das Netzwerk aufgerufen wird. Die Vorgehensweise hängt von Ihrer Distribution ab und davon, ob Sie NetworkManager verwenden.

Wenn Sie diese Befehle als Teil der Anmeldeskripts ausführen müssen, testen Sie die Ressource, die Sie wirklich benötigen, und nicht das Vorhandensein einer IP-Adresse. Wenn Sie beispielsweise testen möchten, ob /net/somenode/somedirgemountet ist, verwenden Sie

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

Wenn Sie Emporkömmling oder System haben ...

dann kannst du es benutzen. Markieren Sie beispielsweise bei Upstart Ihren Job als start on net-device-up eth0( eth0durch den Namen der Schnittstelle ersetzen , die die gewünschte Netzwerkkonnektivität bereitstellt). Siehe Mit Systemd Verursachen, dass ein Skript ausgeführt wird, nachdem das Netzwerk gestartet wurde?

Gilles 'SO - hör auf böse zu sein'
quelle
Ich denke /net/sollte sein /proc/net?
Sebix
@sebix Nein, warum sollte es? Ich spreche nicht über die Netzwerkkonfiguration von Linux. Ich gebe ein Beispiel für einen Mount-Punkt für ein Remote-Dateisystem, der /netein häufiger Speicherort für solche Mount-Punkte ist.
Gilles 'SO - hör auf böse zu sein'
Ok, Sie benötigen also ein bereitgestelltes Netzwerklaufwerk. Gibt es auch eine allgemeinere Lösung?
Sebix
@sebix Eine Lösung für was? Das Erfordernis eines gemounteten Netzwerklaufwerks war ein Beispiel für ein Ziel, kein Beispiel für eine Lösung.
Gilles 'SO - hör auf böse zu sein'
1

Zählen Sie einfach die Ausgabe von ip add showZum Beispiel:

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

Dann können Sie einfach nach der Anzahl der zurückgegebenen Zeilen verzweigen. Sie würden wahrscheinlich nur prüfen, ob es Null ist, und wenn ja, schlafen und die Schleife wiederholen.

Ungetesteter Code zur Veranschaulichung:

while [ 1 ]; do

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

  sleep 1

done
Bratchley
quelle
1

Ping gibt eine 0-Antwort zurück, wenn mindestens ein Versuch erfolgreich war. Sie können den Server, zu dem Sie eine Verbindung herstellen, anpingen, bis er erfolgreich ist.

brwtx
quelle