Come faccio a dire a uno script di attendere che un processo inizi ad accettare richieste su una porta?


33

Ho bisogno di un comando che attenderà che un processo inizi ad accettare richieste su una porta specifica.

C'è qualcosa in Linux che lo fa?

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

...

Risposte:


52

Il miglior test per vedere se un server accetta connessioni è in realtà provare a connettersi. Usa un client normale per qualunque protocollo parli il tuo server e prova un comando no-op.

Se si desidera un client TCP o UDP leggero, è possibile guidare semplicemente dalla shell, utilizzare netcat . Come programmare una conversazione dipende dal protocollo; molti protocolli prevedono che il server chiuda la connessione su un determinato input e quindi netcat uscirà.

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

Puoi anche dire a netcat di uscire dopo aver stabilito la connessione. Restituisce 1 se non è presente alcuna connessione e 0 se è presente, quindi neghiamo il suo output. A seconda della versione di netcat, potrebbe supportare uno o entrambi i seguenti comandi:

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

Un approccio alternativo è attendere che il processo del server apra un socket di ascolto.

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

Se sei su Mac OS, netstat utilizza un formato di output leggermente diverso, quindi vorrai il seguente intead:

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

Oppure potresti voler scegliere come target un ID processo specifico:

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

Non riesco a pensare a nessun modo di reagire al processo iniziando ad ascoltare il socket (che eviterebbe un approccio di polling) a corto di utilizzo ptrace.


Penso che netcat sia la risposta, quindi grazie. Per chiarire, quello che sto cercando di fare è scrivere uno script come parte di una procedura di bilanciamento del carico. Devo avviare un processo, attendere che accetti richieste sulla porta e quindi chiudere l'originale. Se ci sono modi migliori per farlo, piuttosto che scrivere la mia sceneggiatura, sono tutto orecchie.
Will

@Will: Questa è una domanda molto diversa! Ho scritto una risposta diversa.
Gilles 'SO- smetti di essere malvagio' il

1
Mi piace anche la soluzione netcat. Ho uno script che utilizza nc -w 2 </dev/null >/dev/null- se la connessione richiede più di 2 secondi, scade e fallisce - il che è utile per il mio utilizzo.
effimero

Cordiali saluti, non riesco a ottenere 'while nc -q 1 localhost 13000 </ dev / null; dormire 10; fatto 'uno al lavoro. Ritorna immediatamente. Il primo funziona bene però. Grazie!
Ellis Percival

@Flyte nc -q 1 localhost 13000 </dev/nullritorna immediatamente se nessun server è in ascolto, ma ritorna con un codice di errore, quindi il loop lo fa dormire e riprovare qualche secondo dopo.
Gilles 'SO- smetti di essere malvagio'

17

Se hai bash e coreutils (es. Timeout, sleep), ma non nc / lsof / netstat, puoi usare questa soluzione che usa i socket bash magic tcp:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done

Per elaborare, Bash ha la funzione opzionale di connettersi ai socket TCP usando "reindirizzamenti di rete" - gnu.org/software/bash/manual/html_node/…
johntellsall il

7

Seguendo l' esempio precedente con bashtcp sockets magic, ecco una versione avanzata che attende la connessione per un periodo di tempo limitato.

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

La differenza è che se la connessione non era disponibile durante 15s, - non si ripeterà per sempre ma uscirà con il codice di errore.

Ciò è utile negli script init per attendere la disponibilità / disponibilità del servizio dopo l'avvio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.