У меня есть сервер CentOS 5.5, на котором запущен Apache на порту 80, а также некоторые другие приложения. Все работает нормально, пока мне по какой-то причине не понадобится перезапустить процесс httpd. Это возвращает:
sudo /etc/init.d/httpd restart
Stopping httpd: [ OK ]
Starting httpd: (98)Address already in use: make_sock: could not bind to address [::]:80
(98)Address already in use: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
Unable to open logs
Сначала я подумал, что, возможно, httpd завис и все еще работает, но это было не так. Итак, я запустил netstat, чтобы узнать, что использует порт 80:
sudo netstat -tlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 *:7203 *:* LISTEN 24012/java
tcp 0 0 localhost.localdomain:smux *:* LISTEN 3547/snmpd
tcp 0 0 *:mysql *:* LISTEN 21966/mysqld
tcp 0 0 *:ssh *:* LISTEN 3562/sshd
tcp 0 0 *:http *:* LISTEN 3780/python26
Оказывается, мой процесс python взял на себя прослушивание http в момент перезапуска httpd. Итак, я убил python и снова попытался запустить httpd, но столкнулся с той же ошибкой. Снова Netstat:
sudo netstat -tlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 *:7203 *:* LISTEN 24012/java
tcp 0 0 localhost.localdomain:smux *:* LISTEN 3547/snmpd
tcp 0 0 *:mysql *:* LISTEN 21966/mysqld
tcp 0 0 *:ssh *:* LISTEN 3562/sshd
tcp 0 0 *:http *:* LISTEN 24012/java
Теперь мой java-процесс взял на себя прослушивание http. Я убил и это, а затем смог успешно перезапустить httpd.
Но это ужасный обходной путь. Почему эти процессы python и java начнут прослушивать порт 80 сразу после перезапуска httpd? Как решить?
Два других комментария. 1) Процессы java и python запускаются apache из сценария php. Но при перезапуске apache они не должны пострадать. И 2) у меня такая же установка на двух других машинах под управлением Ubuntu, и там нет никаких проблем.
Любые идеи?
Редактировать:
Процесс Java слушает порт 7203, а процесс Python предположительно не слушает ни один порт. По какой-то причине они начинают прослушивать порт 80 при перезапуске apache. Раньше этого не было. На Ubuntu все работает нормально. По какой-то причине на моем текущем компьютере CentOS 5.5 возникает эта проблема.
Проблема может заключаться в том, как Apache запускает подпроцессы. Они могут быть порождены путем разветвления и предоставления клонированным процессам Apache возможности стать другими процессами. Каждый клон наследует все дескрипторы открытых файлов родительского процесса, включая дескриптор открытия порта TCP 80.
Netstat показывает только одно приложение, связанное с дескриптором открытого файла, в то время как три процесса оставляют дескриптор открытым.
Возможные решения вашей проблемы:
Если важно, чтобы подпроцессы выполнялись во время перезапуска Apache, самым простым решением было бы запустить 3 процесса как отдельные системные службы.
Если они зависят от работающего Apache, их также должна завершить команда apache stop. Этого можно добиться, отредактировав сценарий /etc/init.d/apache.
Если вы вынуждены запускать их из Apache, вам нужно запускать их как настоящие «процессы-демоны»!
Я написал создателя демона для PyQt-приложения, вдохновленного http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/. Вы можете запустить этот скрипт из Apache, вызвать exec_as_daemon для каждого из ваших подпроцессов и закрыть его.
# Copyright: (c) 2011 phobie <pydaemon.phobie@safersignup.com>
# License: CC-by-sa 3.0
import os
def exec_as_daemon(s_path_cmd, l_args=[]):
i_pid = os.fork()
if i_pid != 0:
# Always remember to gobble your zombie children
os.wait()
# Back to parent
return
# Detach from parent
os.setsid()
# Do not block any mounts
os.chdir('/')
# Reset file creation rights
os.umask(0)
i_pid = os.fork()
if i_pid != 0:
# Close the direct child process
os._exit(0)
# Get the maximum count of open file handles
try:
import resource
i_fd_max = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if i_fd_max == resource.RLIM_INFINITY:
i_fd_max = 1024
except ImportError:
i_fd_max = 1024
# Try to close all possible file handles
for i_cur_fd in range(0, i_fd_max):
try:
os.close(i_cur_fd)
except OSError:
pass
# Assosiate STDIN with /dev/null
os.open(os.devnull if hasattr(os, "devnull") else '/dev/null', os.O_RDWR)
# STDOUT to /dev/null
os.dup2(0, 1)
# STDERR to /dev/null
os.dup2(0, 2)
l_args.insert(0, s_path_cmd)
# Let the clone become a other process
os.execv(s_path_cmd, l_args)
if __name__ == '__main__':
exec_as_daemon('/usr/bin/java', ['-jar', '/usr/local/bin/apache_helper_daemon.jar'])
exec_as_daemon('/usr/local/bin/apache_helper_daemon.py')
Вы не можете полностью завершить свой главный процесс apache, и его дочерние элементы остаются привязанными к сокетам. Вместо перезапуска запустите сервис httpd stop. Если это не удается правильно завершить, вам необходимо дополнительно изучить приложения java и python, которые вы включили через apache.
Если служба httpd stop работает некорректно, удалите приложения java и python, пока вы не сможете полностью перезапустить. Затем выясните, почему эти процессы не завершаются правильно.
Теоретически только один процесс должен прослушивать данный IP / порт. Если вам нужно, чтобы несколько приложений прослушивали один и тот же порт, вам понадобится установка типа обратного прокси, которая будет определять на основе полученного контента, какой процесс получить сообщение.
Было бы полезно знать, что делают ваши приложения Python и Java. Если они также являются серверами, которые прослушивают порт 80, они застревают в точке открытия порта 80 для прослушивания во время работы Apache, и как только вы убиваете Apache, следующий из очереди процессов проходит и открывает порт. Вам нужно будет изменить коды Python и Java, чтобы прослушивать разные порты.
Странно то, что происходит. В качестве обходного пути используйте reload
вместо restart
:
sudo /etc/init.d/httpd reload
Попробуйте узнать о новом процессе java и python. Вы можете попробовать узнать, когда они запустились, и параметры командной строки:
ps -edf|egrep 'python|java|PID'
Также проверьте /etc/init.d/httpd на все, что связано с java или python.
Используйте инструмент аудита, чтобы узнать, когда программа запущена, кем и т. Д .: