我有一个在端口80上运行Apache的CentOS 5.5服务器以及其他一些应用程序。 所有工作正常,直到我由于某种原因需要重新启动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进程在httpd重启的时候已经接pipe了http。 所以,我杀了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进程已经接pipe了http。 我也杀了,可以成功地重新启动httpd。
但这是一个可怕的解决方法。 为什么这些python和java进程在httpd重启后立即开始监听端口80? 怎么解决?
另外两个意见。 1)java和python进程都是由apache从一个php脚本启动的。 但是,当Apache重新启动,他们不应该受到影响。 和2)我有两台运行Ubuntu的其他机器上的相同的设置,那里没有问题。
有任何想法吗?
编辑:
Java进程侦听端口7203,python进程据说不侦听任何端口。 出于某种原因,当Apache重新启动时,他们开始听80端口。 这从来没有发生过。 在Ubuntu上它运行良好。 出于某种原因,在我目前的CentOS 5.5机器上,出现这个问题。
问题可能是Apache如何启动subprocess的方式。 他们可能会被派生,并让克隆的Apache进程成为其他进程。 每个克隆都会inheritance父进程的所有打开的文件句柄,包括TCP端口80的打开句柄。
Netstat只显示与打开文件句柄关联的一个应用程序,而三个进程则保持句柄处于打开状态。
您的问题可能的解决scheme:
如果在Apache重启期间保持subprocess运行非常重要,最简单的解决scheme是将3进程作为单独的系统服务启动。
如果他们依赖于运行的Apache,那么“apache stop”命令也应该终止它们。 这可以通过编辑/etc/init.d/apache脚本来实现。
如果你不得不从Apache启动它们,你需要将它们作为真正的“守护进程”启动!
我编写了一个由http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/启发的PyQt应用的守护进程创build器。 你可以从Apache启动这个脚本,为每个subprocess调用exec_as_daemon并closures它。
# Copyright: (c) 2011 phobie <[email protected]> # 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')
理论上,只有一个进程应该监听给定的IP /端口。 如果您需要多个应用程序在同一个端口上侦听,则需要一个反向代理types的设置,它将根据收到的内容来确定获取消息的过程。
知道你的Python和Java应用程序正在做什么将是有帮助的。 如果他们也是在端口80上侦听的服务器,那么当Apache运行时,他们会在打开端口80的时候卡住,只要您杀死Apache,进程队列中的下一个端口就会通过并打开端口。 您将需要更改您的Python和Java代码以侦听不同的端口。
你没有清理closures你的Apache主进程,它的孩子留在套接字。 而不是运行重新启动,运行服务httpd停止。 如果不能完全退出,则需要进一步调查通过apache启用的java和python应用程序。
如果服务httpd stop无法正常工作,请卸载您的java和python应用程序,直到可以干净地重新启动为止。 然后,调查为什么这些进程没有正确终止。
奇怪发生了什么事 作为解决方法使用reload
而不是restart
:
sudo /etc/init.d/httpd reload
尝试找出有关新的Java和Python进程。 你可以试着找出它们何时开始,以及命令行参数:
ps -edf|egrep 'python|java|PID'
检查/etc/init.d/httpd是否与java或python相关。
使用审计工具来了解程序何时启动,由谁等: