我正在使用 python bottle web 框架来创建一个服务管理器,所以我为服务创建了端点,重新启动/停止我正在使用时发生的有线事情
os.system('service apache2 restart')
或者
os.system('/etc/init.d/apache2 restart')
Apache 接管了我的 Bottle 应用程序的端口,所以如果我正在运行lsof -i :8080
(8080 是我的 Bottle 应用程序端口),我会看到
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 27396 root 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27426 root 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27428 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27429 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27430 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27432 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27433 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
apache2 27435 www-data 3u IPv4 1298282 0t0 TCP *:http-alt (LISTEN)
文件 /etc/apache2/ports 具有以下内容
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
当然,如果我在 shell 中运行相同的命令,一切都会按预期进行
注意:python 脚本以 root 身份运行
答案1
这是因为默认情况下,子进程会继承其父进程的文件描述符。
由于您的 Web 应用程序打开了此端口,因此它会将os.system
请求发送到正在运行的 Apache Web 服务器。
您需要改变您的python代码来执行以下操作。
- 称呼
os.fork()
- 关闭您的 Web 应用程序所使用的监听服务器端口的文件描述符。(注意不要 不是调用
shutdown
它。 - 拨打您的
os.system()
请求。 - 退出你的分叉进程。
较新版本的 Python 引入了一种默认行为,即FD_CLOEXEC
在所有文件描述符上添加属性以避免此行为。您也可以使用该fcntl
模块在监听套接字上自己执行相同的操作,但这可能会破坏应用程序的其他方面,因此您需要对此进行测试。