Jak nakazać skryptowi, aby poczekał, aż proces zacznie akceptować żądania na porcie?

33

Potrzebuję polecenia, które będzie czekać na proces, aby rozpocząć przyjmowanie żądań na określonym porcie.

Czy jest coś takiego w Linuksie?

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

...
Wola
źródło

Odpowiedzi:

52

Najlepszym testem, aby sprawdzić, czy serwer akceptuje połączenia, jest próba połączenia. Użyj zwykłego klienta dla dowolnego protokołu, który mówi Twój serwer, i wypróbuj polecenie no-op.

Jeśli chcesz mieć lekkiego klienta TCP lub UDP, możesz po prostu jeździć z powłoki, użyj netcat . Sposób zaprogramowania rozmowy zależy od protokołu; w wielu protokołach serwer zamyka połączenie na określonym wejściu, a następnie netcat kończy działanie.

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

Możesz także powiedzieć netcat, aby zakończył pracę po ustanowieniu połączenia. Zwraca 1, jeśli nie ma połączenia, i 0, jeśli tak, dlatego negujemy jego wynik. W zależności od wersji programu netcat może on obsługiwać jedno lub oba z następujących poleceń:

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

Alternatywnym podejściem jest czekanie, aż proces serwera otworzy gniazdo nasłuchujące.

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

Jeśli korzystasz z systemu Mac OS, netstat używa nieco innego formatu wyjściowego, więc powinieneś mieć następujące intead:

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

Lub możesz kierować na określony identyfikator procesu:

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

Nie mogę wymyślić żadnego sposobu, aby zareagować na proces zaczynający nasłuchiwać gniazda (co uniknęłoby podejścia odpytywania) bez użycia ptrace.

Gilles „SO- przestań być zły”
źródło
Myślę, że Netcat jest odpowiedzią, więc dziękuję. Aby wyjaśnić, próbuję napisać skrypt w ramach procedury równoważenia obciążenia. Muszę rozpocząć proces, poczekać, aż przyjmie on żądania na porcie, a następnie zamknij oryginał. Jeśli są lepsze sposoby na zrobienie tego, niż pisanie własnego scenariusza, jestem cała w uszach.
Czy
@Will: To jest zupełnie inne pytanie! Napisałem inną odpowiedź.
Gilles „SO- przestań być zły”
1
Lubię też rozwiązanie Netcat. Mam skrypt używający nc -w 2 </dev/null >/dev/null- jeśli połączenie trwa dłużej niż 2 sekundy, upłynie limit czasu i nie powiedzie się - co jest przydatne do mojego użycia.
ephemient
Do twojej wiadomości, nie mogę dostać 'while nc -q 1 localhost 13000 </ dev / null; śpij 10; skończone do pracy. Po prostu wraca natychmiast. Pierwszy działa jednak dobrze. Dzięki!
Ellis Percival,
@Flyte nc -q 1 localhost 13000 </dev/nullzwraca natychmiast, jeśli żaden serwer nie nasłuchuje, ale zwraca kod błędu, więc pętla uśpia i próbuje ponownie kilka sekund później.
Gilles „SO- przestań być zły”
17

Jeśli masz bash i coreutils (np. Limit czasu, sen), ale nie masz nc / lsof / netstat, możesz użyć tego rozwiązania, które wykorzystuje gniazda bash magic tcp:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done
kanaka
źródło
Aby rozwinąć, Bash ma opcjonalną funkcję łączenia się z gniazdami TCP za pomocą „przekierowań sieciowych” - gnu.org/software/bash/manual/html_node/…
johntellsall
7

Podobnie jak w poprzednim przykładzie z bashmagicznymi gniazdami Tcp, tutaj jest ulepszona wersja, która czeka na połączenie przez ograniczony czas.

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

Różnica polega na tym, że jeśli połączenie nie było dostępne podczas 15s, - nie zapętla się na zawsze, ale kończy działanie z kodem błędu.

Jest to przydatne w skryptach init do oczekiwania na gotowość / dostępność usługi po uruchomieniu.

arma
źródło