Как сказать сценарию ждать, пока процесс начнет принимать запросы через порт?


33

Мне нужна команда, которая будет ждать, пока процесс начнет принимать запросы на определенный порт.

Есть ли что-то в Linux, что делает это?

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

...

Ответы:


52

Лучший тест, чтобы увидеть, принимает ли сервер подключения, - это попытаться подключиться. Используйте обычный клиент для любого протокола, на котором говорит ваш сервер, и попробуйте команду no-op.

Если вам нужен облегченный TCP или UDP-клиент, который вы можете использовать просто из оболочки, используйте netcat . Как запрограммировать разговор зависит от протокола; во многих протоколах сервер закрывает соединение на определенном входе, и затем netcat завершает работу.

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

Вы также можете указать netcat выйти после установления соединения. Возвращает 1, если нет соединения, и 0, если есть, поэтому мы отрицаем его вывод. В зависимости от вашей версии netcat, он может поддерживать одну или обе из следующих команд:

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

Альтернативный подход - дождаться, пока процесс сервера откроет сокет прослушивания.

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

Если вы работаете в Mac OS, netstat использует немного другой формат вывода, поэтому вам понадобится следующий intead:

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

Или вы можете выбрать целевой идентификатор процесса:

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

Я не могу придумать, как реагировать на процесс, начинающий слушать сокет (который позволит избежать использования опроса), за исключением использования ptrace.


Я думаю, что Netcat является ответом, так что спасибо. Чтобы уточнить, что я пытаюсь сделать, это написать скрипт как часть процедуры балансировки нагрузки. Мне нужно запустить процесс, подождать, пока он примет запросы на порт, а затем выключить оригинал. Если есть более эффективные способы сделать это, чем писать собственный сценарий, я весь в ушах.
Будет

@Will: это совсем другой вопрос! Я написал другой ответ.
Жиль "ТАК - перестань быть злым"

1
Мне тоже нравится решение Netcat. У меня есть скрипт, использующий nc -w 2 </dev/null >/dev/null- если соединение длится более 2 секунд, оно истекает и завершается неудачно - что удобно для моего использования.
ephemient

К вашему сведению, я не могу получить 'while nc -q 1 localhost 13000 </ dev / null; спать 10; сделано один на работу. Это просто возвращается немедленно. Первый работает нормально, хотя. Благодарность!
Эллис Персиваль

@Flyte nc -q 1 localhost 13000 </dev/nullнемедленно возвращается, если сервер не прослушивает, но возвращается с кодом ошибки, поэтому цикл переводит его в спящий режим и повторяет попытку через несколько секунд.
Жиль "ТАК - перестань быть злым"

17

Если у вас есть bash и coreutils (например, timeout, sleep), но нет nc / lsof / netstat, вы можете использовать это решение, которое использует сокеты bash magic tcp:

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

Для разработки, Bash имеет дополнительную функцию подключения к TCP сокетам с помощью «сетевого переназначения» - gnu.org/software/bash/manual/html_node/...
johntellsall

7

Следуя предыдущему примеру с bashволшебством сокетов tcp, вот улучшенная версия, которая ожидает подключения в течение ограниченного периода времени.

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

Разница в том, что если соединение не было доступно во время 15s, - оно не будет зациклено, а завершится с кодом ошибки.

Это полезно в сценариях инициализации для ожидания готовности / доступности службы после запуска.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.