3

Я разработчик, работающий в OS X на Eclipse. Ошибка, над которой я работал, чтобы исправить в веб-приложении, приводит к некоторому очень странному поведению при сбросе экземпляра Tomcat, приводящему к следующему сообщению об ошибке при принудительном завершении работы и перезапуске сервера (он не будет отключаться корректно, вероятно из-за ошибка, которую я пытаюсь исправить, поэтому мне нужно ее kill , и kill -9 <pid> и внутреннее "принудительное завершение" в Eclipse дают одинаковое поведение):

Несколько портов (23432, 34543), необходимых для сервера Tomcat v8.0 на локальном хосте, уже используются. Возможно, сервер уже запущен в другом процессе, или системный процесс может использовать порт. Чтобы запустить этот сервер, вам нужно остановить другой процесс или изменить номер порта (ов).

Это хорошо, я долго работал над этим, и обычно это означает, что Tomcat еще где-то работает, просто нужно удалить его, и все будет работать.

Однако lsof(1) не перечисляет никаких активных процессов, удерживающих этот порт:

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

Я проверил, что порты действительно используются с помощью небольшого скрипта Python, просто чтобы убедиться, что Eclipse не ошибается:

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()

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

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

Существует а (java) процесс зомби плавающего вокруг с PID на сервере Tomcat , который я первоначально убил, и я подозреваю , что этот человек имеет что - то делать с ним:

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

Есть ли способ , я могу освободить порты, которые используются без перезагрузки или выхода из системы ?

Это происходит каждый раз, когда я воссоздаю свою ошибку, и это огромная трата времени, чтобы останавливаться и перезагружаться при каждом проходе отладки.

В Linux я, вероятно, запустил бы gdb -p PID и close(<fdnum>) но в OS X я даже не могу найти, какой (если есть) дескриптор файла ссылается на этот адрес.

1 ответ1

0

Я полагаю, netstat тоже не работает?

У меня было то же самое со мной в Linux, но очень давно (я уверен, что это было ядро 2.0.36). Порт подсел на мой eth1 . Я отключил сетевой адаптер и снова включил его через пару секунд. Это «очистило» структуры ядра, которые удерживали порт в «полуоткрытом» состоянии.

Я не знаю, можете ли вы вызвать down в петлевом интерфейсе и заставить его работать, но, возможно, стоит попробовать.

Вы можете попробовать отправить SIGCHLD на launchd и посмотреть, что произойдет. Или даже SIGHUP, чтобы сказать ему, что нужно переинициализировать и (возможно) пожинать детей-зомби (kill -HUP 1 , kill -s HUP 1 .

Другой трюк, который стоит попробовать, - это "обернуть" экземпляр Tomcat сценарием запуска, который запустит настоящий Tomcat и будет ждать его закрытия. Затем вы можете увидеть, что произойдет, когда сам скрипт-обертка будет убит, или вы можете попробовать прослушать мошеннический процесс Java, чтобы убедиться, что он не станет зомби.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .