Wie sage ich einem Skript, dass es warten soll, bis ein Prozess Anforderungen an einem Port annimmt?

33

Ich benötige einen Befehl, der darauf wartet, dass ein Prozess Anforderungen an einem bestimmten Port annimmt.

Gibt es etwas in Linux, das das macht?

while (checkAlive -host localhost -port 13000 == false)
  do some waiting

...
Wille
quelle

Antworten:

52

Der beste Test, um festzustellen, ob ein Server Verbindungen akzeptiert, besteht darin, tatsächlich eine Verbindung herzustellen. Verwenden Sie einen regulären Client für jedes Protokoll, das Ihr Server spricht, und versuchen Sie es mit einem No-Op-Befehl.

Wenn Sie einen schlanken TCP- oder UDP-Client möchten, den Sie einfach über die Shell fahren können, verwenden Sie netcat . Wie eine Konversation programmiert wird, hängt vom Protokoll ab. Bei vielen Protokollen beendet der Server die Verbindung über eine bestimmte Eingabe, und Netcat wird dann beendet.

while ! echo exit | nc localhost 13000; do sleep 10; done

Sie können netcat auch anweisen, nach dem Herstellen der Verbindung zu beenden. Es gibt 1 zurück, wenn keine Verbindung besteht, und 0, wenn dies der Fall ist, negieren wir seine Ausgabe. Abhängig von Ihrer Netcat-Version werden möglicherweise einer oder beide der folgenden Befehle unterstützt:

while ! nc -z localhost 13000 </dev/null; do sleep 10; done
while ! nc -q 1 localhost 13000 </dev/null; do sleep 10; done

Alternativ können Sie warten, bis der Serverprozess einen Listening-Socket geöffnet hat.

while netstat -lnt | awk '$4 ~ /:13000$/ {exit 1}'; do sleep 10; done

Wenn Sie unter Mac OS arbeiten, verwendet netstat ein etwas anderes Ausgabeformat, sodass Sie Folgendes wünschen:

while netstat -lnt | awk '$4 ~ /\.13000$/ {exit 1}'; do sleep 10; done

Oder Sie möchten möglicherweise auf eine bestimmte Prozess-ID abzielen:

while ! lsof -n -Fn -p $pid | grep -q '^n.*:13000$'; do sleep 10; done

Ich kann mir keine Möglichkeit vorstellen, auf den Prozess zu reagieren, wenn ich anfange, auf den Socket zu hören (was einen Polling-Ansatz vermeiden würde), ohne ihn zu verwenden ptrace.

Gilles 'SO - hör auf böse zu sein'
quelle
Ich denke, Netcat ist die Antwort, also danke. Um dies zu verdeutlichen, versuche ich, ein Skript im Rahmen eines Lastenausgleichs zu schreiben. Ich muss einen Prozess starten, warten, bis er Anforderungen auf dem Port akzeptiert, und dann das Original herunterfahren. Wenn es dafür bessere Möglichkeiten gibt, als mein eigenes Drehbuch zu schreiben, bin ich ganz Ohr.
Wird
@ Will: Das ist eine ganz andere Frage! Ich habe eine andere Antwort geschrieben.
Gilles 'SO- hör auf böse zu sein'
1
Ich mag Netcat-Lösung auch. Ich verwende ein Skript. nc -w 2 </dev/null >/dev/nullWenn die Verbindung länger als 2 Sekunden dauert, tritt eine Zeitüberschreitung auf und die Verbindung schlägt fehl. Dies ist praktisch für meine Verwendung.
Ephemient
Zu Ihrer Information, ich kann die 'while nc -q 1 localhost 13000 </ dev / null; schlafe 10; getan, um zu arbeiten. Es kehrt einfach sofort zurück. Der erste funktioniert aber gut. Vielen Dank!
Ellis Percival
@Flyte nc -q 1 localhost 13000 </dev/nullkehrt sofort zurück, wenn kein Server empfangsbereit ist. Es wird jedoch ein Fehlercode zurückgegeben, sodass die Schleife den Ruhezustand aktiviert und es einige Sekunden später erneut versucht.
Gilles 'SO - hör auf böse zu sein'
17

Wenn Sie bash und coreutils haben (z. B. timeout, sleep), aber nicht nc / lsof / netstat, können Sie diese Lösung verwenden, die bash magic tcp-Sockets verwendet:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done
Kanaka
quelle
Bash hat die optionale Funktion, über "Netzwerkumleitungen" eine Verbindung zu TCP-Sockets herzustellen
gnu.org/software/bash/manual/html_node/…
7

Nach dem vorherigen Beispiel mit bashtcp sockets magic ist hier eine erweiterte Version, die während einer begrenzten Zeitspanne auf die Verbindung wartet.

timeout 15 bash -c 'until echo > /dev/tcp/localhost/13000; do sleep 0.5; done'

Der Unterschied besteht darin, dass, wenn die Verbindung während nicht verfügbar war 15s, sie nicht für immer wiederholt wird, sondern mit dem Fehlercode beendet wird.

Dies ist in Init-Skripten nützlich, um nach dem Start auf die Servicebereitschaft / -verfügbarkeit zu warten.

arma
quelle