Unterschale in den Hintergrund setzen oder Befehl in den Hintergrund stellen

7

Ich habe zwei Bash-Skripte, die versuchen, Hosts zu überprüfen, die aktiv sind:

Skript 1:

#!/bin/bash 
for ip in {1..254}; do
    ping -c 1 192.168.1.$ip | grep "bytes from" | cut -d" " -f 4 | cut -d ":" -f 1 &
done

Skript 2:

#!/bin/bash 
for ip in {1..254}; do
    host=192.168.1.$ip
    (ping -c 1 $host > /dev/null 
    if [ "$?" = 0 ]
    then 
        echo $host
    fi) &
done

Da ich einen großen Bereich überprüfe, möchte ich jeden Ping-Befehl parallel verarbeiten. Mein zweites Skript scheint jedoch fehlgeschlagene Verzweigungsversuche aufgrund von Ressourcenbeschränkungen nicht erneut zu versuchen. Dies führt dazu, dass das zweite Skript inkonsistente Ergebnisse aufweist, während mein erstes Skript konstante Ergebnisse liefert, obwohl beide zeitweise nicht verzweigen. Kann mir das jemand erklären? Gibt es überhaupt eine Möglichkeit, ausgefallene Gabeln erneut zu versuchen?

MykelXIII
quelle
apt-get install fping: - / (oder nmap -sP)
derobert
@derobert Ich weiß, dass nmap funktioniert. Ich möchte nur versuchen, einen Ping-Sweep für dieses Experiment durchzuführen.
MykelXIII
1
Der richtige Weg, dies zu tun, besteht darin, zu verfolgen, wie viele untergeordnete Prozesse Sie ausgeführt haben, und eine vernünftige Zahl einzuhalten. Abgesehen paralleldavon, dass Sie Dienstprogramme (z. B. ) verwenden, um dies für Sie zu tun, müssen Sie nachverfolgen, von welchen Kindern Sie erzeugt haben (Sie erhalten die PID $!, warten Sie, bis sie beendet werden (und finden Sie ihren Beendigungscode heraus) wait. usw. Persönlich
wechsle

Antworten:

4

Es gibt bereits eine Antwort, die ein verbessertes Code-Snippet für die Aufgabe liefert, auf die sich die ursprünglichen Posterfragen bezogen, während sie möglicherweise noch nicht direkter auf die Frage geantwortet hat.

Die Frage betrifft Unterschiede von

  • A) Hintergrund eines "Befehls" direkt, vs.
  • B) Eine Unterschale in den Hintergrund stellen (dh mit einer ähnlichen Aufgabe)

Lassen Sie uns diese Unterschiede überprüfen, indem wir 2 Tests ausführen

# A) Backgrounding a command directly
sleep 2 & ps

Ausgänge

[1] 4228
  PID TTY          TIME CMD
 4216 pts/8    00:00:00 sh
 4228 pts/8    00:00:00 sleep

während

# A) backgrounding a subhell (with similar tas)
( sleep 2; ) & ps

gibt so etwas aus wie:

[1] 3252
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 sh
 3252 pts/8    00:00:00 sh
 3253 pts/8    00:00:00 ps
 3254 pts/8    00:00:00 sleep

** Testergebnisse:**

In diesem Test (der nur a sleep 2ausführt) unterscheidet sich die Subshell-Version tatsächlich, da zwei untergeordnete Prozesse (dh zwei fork()/ execOperationen und PID) und damit mehr als der direkte Hintergrund des Befehls verwendet würden.

In der script 1Frage war der Befehl jedoch kein einzelner, sleep 2ssondern ein pipevon 4 Befehlen, die wir in einem zusätzlichen Fall testen

  • C) Hintergrund einer Pipe mit 4 Befehlen
# C) Backgrounding a pipe with 4 commands
sleep 2s | sleep 2s | sleep 2s | sleep 2s & ps

ergibt dies

[2] 3265
  PID TTY          TIME CMD
 3216 pts/8    00:00:00 bash
 3262 pts/8    00:00:00 sleep
 3263 pts/8    00:00:00 sleep
 3264 pts/8    00:00:00 sleep
 3265 pts/8    00:00:00 sleep
 3266 pts/8    00:00:00 ps

und zeigt, dass das in der Tat script 1eine viel höhere Belastung in Bezug auf PIDsund fork()s wäre.

Als grobe Schätzung hätte das Skript etwa 254 * 4 ~ = 1000 PIDs und damit sogar mehr als script 2bei 254 * 2 ~ = 500 PIDs verwendet. Ein Problem, das aufgrund der Erschöpfung der PIDs auftritt, scheint noch unwahrscheinlich, da höchstens Linux-Boxen

$ cat /proc/sys/kernel/pid_max
32768

gibt Ihnen 32x mal die auch für Fall benötigt PIDs script 1und die Prozesse / beteiligten Programme (dh sed, pingscheinen, usw.) auch unwahrscheinlich , dass die inkonstant Ergebnisse zu verursachen.

Wie von Benutzer @derobert erwähnt, bestand das eigentliche Problem hinter dem Fehler darin, scriptsdass der waitBefehl fehlte. Dies bedeutet, dass nach dem Hintergrund der Befehle in der Schleife das Ende des Skripts und damit die Shell dazu führte, dass alle untergeordneten Prozesse beendet wurden.

Menschlichkeit UND Frieden
quelle
gelöschter
@ MykelXIII :). neugierig sein: was meinst du genauer mit "das Skript erschöpfte Ressourcen"? Wie messen / testen Sie das? Eine Ressource könnte die Verwendung einer PID (es gibt keine unbegrenzten Prozess-IDs), Speicher, Cputime sein. Was haben Sie gemeint?
Menschheit und
Entschuldigung, ich habe einen Fehler beim Verstehen Ihrer Antwort gemacht. Es macht jetzt Sinn. Das erste Skript verwendete tatsächlich mehr Ressourcen. Ich bin jedoch neugierig, ob mein erstes Skript nicht gewartet hat und dennoch konsistente Ergebnisse liefert. Bedeutet das, dass die untergeordneten Prozesse schneller abgeschlossen wurden als der übergeordnete Prozess?
MykelXIII
@MykelXIII Meine Vermutung ist folgende: In beiden Skripten waitgibt es eindeutig ein Rennen , da es keine Garantie dafür gibt, die erzeugten Unterprozesse nicht vorzeitig zu beenden ..... Das Ende ist, nachdem das Skript die for-Schleife durchlaufen hat ... script 1liefert bessere Ergebnisse, weil (a) jede In script1-Schleife länger dauert ( script1: Pipe mit 4 Prozessen script2starten VS : Subshell starten), bis das Material in den Hintergrund gestellt wurde. Zusätzlich werden die in (b) script2ping wird nur ausgeführt , nachdem der Subshell war fork()und damit später als in script1und es dauert eine andere if , [und echoBefehl ....
humanityANDpeace
... zu beenden, das ist die Zeit, script2die nicht zur Verfügung steht, wenn die Schleife endet (siehe (a) schnell)
humanityANDpeace
2

Dies wird das tun, was Sie erwarten:

#!/bin/bash
function_ping(){
    if ping -c 1 -w 5 $1 &>/dev/null; then 
        echo "UP: $1"
    else
        echo "DOWN $1" 
    fi
}
for ip in {1..254}; do
        function_ping 192.168.1.$ip &  
done
wait 

Speichern Sie es als Parallelping und führen Sie es aus.

Es hilft dir? Es kann in eine große Funktion umgewandelt werden, die auch in einer schnellen while-Schleife verwendet werden kann, sodass Sie Ihre Fantasieprogrammierung damit verwenden können.

Hinweis: Sie müssen bash verwenden.

Luciano Andress Martini
quelle
Es funktioniert, aber ich habe das & in der ping -c 1 -w 5 $ 1 & -Anweisung entfernt. Können Sie erklären, warum es 2 & gibt? Eine im Funktionsaufruf und eine im Ping-Aufruf? Kann ich auch fragen, warum Subshells fehlschlagen, während Funktionen nicht in den Hintergrund gestellt werden?
MykelXIII
Das & in der ping-Anweisung hilft bei der Umleitung der Ping-Ausgabe nach / dev / null. Dies bedeutet, dass alle Standardausgaben des Befehls umgeleitet werden müssen, sodass nichts mit dem anderen "&" zusammenhängt, das die Funktion im Hintergrund ausführt Für das Umleitungszeichen (>) funktioniert dies jedoch, wenn sich dieses Zeichen '&' auf das Zeichen '>' stützt. Ihr Skript funktioniert auch sehr gut. Sie müssen nach der Anweisung 'done' warten, da das Skript sonst nicht auf die Beendigung der Hintergrundprozesse wartet. Stellen Sie sicher, dass Sie es von bash und nicht von sh wie 'sh thescript' ausführen.
Luciano Andress Martini
Was ist die entscheidende Information der Antwort? Ist es zu verwenden wait, um auf die Beendigung der untergeordneten Prozesse im Hintergrund zu warten, ja? Oder war der entscheidende Punkt die Verwendung einer Shell-Funktion ? Wie in dem Kommentar von @LucianoAndressMartini geschrieben, scheint es das zu sein wait, aber dies wird aus der Antwort nicht wirklich klar.
Menschlichkeit und
Es ist eine alte Frage, aber Sie haben Recht, Menschlichkeit. Ich habe die Frage im Kommentar geklärt, weil ich nach dem Schreiben der Antwort festgestellt habe, dass das ursprüngliche Skript funktioniert.
Luciano Andress Martini