Como digo a um script para aguardar que um processo comece a aceitar solicitações em uma porta?

33

Preciso de um comando que aguarde um processo começar a aceitar solicitações em uma porta específica.

Existe algo no linux que faz isso?

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

...
Vai
fonte

Respostas:

52

O melhor teste para ver se um servidor está aceitando conexões é realmente tentar se conectar. Use um cliente comum para qualquer protocolo que seu servidor fale e tente um comando no-op.

Se você deseja um cliente TCP ou UDP leve, pode dirigir simplesmente a partir do shell, use o netcat . Como programar uma conversa depende do protocolo; muitos protocolos fazem com que o servidor feche a conexão em uma determinada entrada e o netcat será encerrado.

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

Você também pode dizer ao netcat para sair depois de estabelecer a conexão. Retorna 1 se não houver conexão e 0 se houver, e negamos sua saída. Dependendo da sua versão do netcat, ele pode oferecer suporte a um ou aos dois comandos a seguir:

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

Uma abordagem alternativa é aguardar o processo do servidor abrir um soquete de escuta.

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

Se você estiver no Mac OS, o netstat usa um formato de saída ligeiramente diferente; portanto, você deseja o seguinte:

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

Ou você pode desejar segmentar um ID de processo específico:

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

Não consigo pensar em nenhuma maneira de reagir ao processo que começa a ouvir o soquete (o que evitaria uma abordagem de votação) antes de usar ptrace.

Gilles 'SO- parar de ser mau'
fonte
Acho que netcat é a resposta, então obrigado. Para esclarecer, o que estou tentando fazer é escrever um script como parte de um procedimento de balanceamento de carga. Preciso iniciar um processo, esperar que ele aceite solicitações na porta e depois desligar o original. Se há maneiras melhores de fazer isso, em vez de escrever meu próprio roteiro, sou todo ouvidos.
Will
@ Will: Essa é uma pergunta muito diferente! Eu escrevi uma resposta diferente.
Gilles 'SO- stop be evil'
1
Eu também gosto da solução netcat. Eu tenho um script usando nc -w 2 </dev/null >/dev/null- se a conexão demorar mais de 2 segundos, atinge o tempo limite e falha - o que é útil para o meu uso.
ephemient
Para sua informação, não consigo obter o 'while nc -q 1 localhost 13000 </ dev / null; dorme 10; feito 'um para trabalhar. Apenas retorna imediatamente. O primeiro funciona bem embora. Obrigado!
Ellis Percival
O @Flyte nc -q 1 localhost 13000 </dev/nullretorna imediatamente se nenhum servidor estiver escutando, mas retorna com um código de erro, portanto o loop faz com que ele durma e tente novamente alguns segundos depois.
Gilles 'SO- stop be evil'
17

Se você possui bash e coreutils (por exemplo, tempo limite, suspensão), mas não nc / lsof / netstat, pode usar esta solução que usa soquetes bash magic tcp:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done
kanaka
fonte
Para elaborar, o Bash tem o recurso opcional de conectar-se aos soquetes TCP usando "redirecionamentos de rede" - gnu.org/software/bash/manual/html_node/…
johntellsall
7

Seguindo o exemplo anterior com bashtcp sockets magic, aqui está uma versão aprimorada que aguarda conexão durante um período limitado de tempo.

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

A diferença é que, se a conexão não estava disponível durante 15s, - ela não funcionará para sempre, mas será encerrada com o código de erro.

Isso é útil nos scripts init para aguardar a disponibilidade / disponibilidade do serviço após a inicialização.

arma
fonte