Como liberar uma porta no OS X quando lsof (1) relata que não está em uso

3

Eu sou um desenvolvedor trabalhando no OS X no Eclipse. Um bug que eu tenho trabalhado para corrigir em um aplicativo da web resulta em algum comportamento muito estranho ao redefinir uma instância do Tomcat, resultando na seguinte mensagem de erro ao forçar um desligamento e reinicialização do servidor (ele não shutdown cleanly, provavelmente devido ao bug que estou tentando corrigir, então eu preciso de kill it, kill -9 <pid> e "force terminate" interno do Eclipse dão o mesmo comportamento):

Several ports (23432, 34543) required by Tomcat v8.0 Server at localhost are already in use. The server may already be running in another process, or a system process may be using the port. To start this server you will need to stop the other process or change the port number(s).

Tudo bem, eu trabalhei com esse material há muito tempo e normalmente isso significa que o Tomcat ainda está rodando em algum lugar, só precisa removê-lo e as coisas funcionarão.

No entanto, lsof(1) não lista lista nenhum processo ativo nessa porta:

user@yosemite ~ %  sudo lsof -Pan -i tcp -i udp | grep 23432
COMMAND    PID           USER   FD   TYPE             DEVICE SIZE/OFF   NODE NAME
launchd      1           root   23u  IPv6 0x57073763bfdd9c27      0t0    TCP *:5900 (LISTEN)
launchd      1           root   26u  IPv4 0x57073763bfddfb77      0t0    TCP *:5900 (LISTEN)
launchd      1           root   30u  IPv6 0x57073763bfdd9727      0t0    TCP [::1]:631 (LISTEN)
launchd      1           root   31u  IPv6 0x57073763bfdd9c27      0t0    TCP *:5900 (LISTEN)
launchd      1           root   32u  IPv4 0x57073763bfddf2a7      0t0    TCP 127.0.0.1:631 (LISTEN)
launchd      1           root   34u  IPv6 0x57073763bfdd9227      0t0    TCP *:22 (LISTEN)
launchd      1           root   37u  IPv4 0x57073763bfdde9d7      0t0    TCP *:22 (LISTEN)
launchd      1           root   41u  IPv4 0x57073763bfddfb77      0t0    TCP *:5900 (LISTEN)
launchd      1           root   47u  IPv4 0x57073763bfddf2a7      0t0    TCP 127.0.0.1:631 (LISTEN)
...
user@yosemite ~ %  sudo lsof -Pan -i tcp -i udp | grep 23432

Eu verifiquei que as portas estão realmente em uso através de um pequeno script python, apenas para ter certeza de que o Eclipse não está errado:

user@yosemite ~ % cat socket_open.py
#!/usr/bin/env python
import sys, traceback, socket

HOST=''
PORT = int(sys.argv[1])

sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Attempting to bind '%s':%s" % (HOST, PORT)
try:
    sck.bind((HOST, PORT))
    print sck.getsockname()
except Exception as exc:
    traceback.print_exc()

Simples, tente ligar à mesma porta e lançar uma exceção se não funcionar.

user@yosemite ~ % sudo python socket_open.py 23432
Password:
Attempting to bind '':23432
Traceback (most recent call last):
  File "socket_open.py", line 10, in <module>
    sck.bind((HOST, PORT))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 48] Address already in use

Existe um processo zombie (java) flutuando com o PID do Tomcat que eu matei originalmente, e eu suspeito que esse sujeito tenha algo a ver com isso:

user@yosemite ~ % ps wwwaux | grep java | grep -v 'grep'
user          975   0.0  0.0        0      0   ??  ?E   11:15AM   0:00.00 (java)

Existe qualquer jeito que eu possa liberar as portas que estão em uso sem reiniciar ou sair?

Isso acontece toda vez que eu recrojo meu bug e é um grande desperdício de tempo ter que parar e reinicializar em cada passagem de depuração.

No Linux, eu provavelmente rodaria gdb -p PID e close(<fdnum>) , mas no OS X eu não consigo nem encontrar qual (se algum) descritor de arquivo se refere a esse endereço.

    
por javanix 14.08.2015 / 20:56

1 resposta

0

Suponho que netstat também não esteja funcionando?

Eu tive essa mesma coisa acontecendo comigo no Linux, mas há muito tempo atrás (eu tenho certeza que era o kernel 2.0.36). A porta foi conectada no meu eth1 . O que fiz foi desativar o adaptador de rede e reativá-lo alguns segundos depois. Isso 'limpou' as estruturas do kernel que mantinham a porta em seu estado "semi-aberto".

Não sei se você pode emitir um down na interface de loopback e fazê-lo funcionar, mas talvez valha a pena tentar.

Você pode tentar enviar um SIGCHLD para launchd e ver o que acontece. Ou até mesmo um SIGHUP para dizer para reiniciar e (possivelmente) colher crianças zumbis ( kill -HUP 1 , kill -s HUP 1 .

Outro truque a ser tentado seria "envolver" a instância do Tomcat com um script de inicialização que executaria o Tomcat verdadeiro e aguardaria o fechamento dele. Então você pode ver o que acontece quando o script wrapper é morto, ou você pode tentar ouvir o processo java desonesto para garantir que ele não se torne um zumbi.

    
por 17.08.2015 / 16:40