Python脚本未收到监控程序发送的退出信号
我正在运行一个Python脚本,这个脚本创建了一个Tornado服务器,而这个服务器是通过supervisor来管理的。每当我执行supervisorctl reload命令(通常是在部署之后),我希望能优雅地关闭所有的WebSocket客户端连接。
我遇到的问题是,当supervisor杀掉我的服务器时,我无法调用一个特定的函数,但如果我用kill命令发送信号,或者在控制台运行并用Control+C结束进程时,这个函数就能正常工作。我尝试了其他信号和配置,但都没有成功。
import signal, sys
def clean_resources(signum, frame):
print "SIG: %d, clean me" % signum
sys.exit(0)
if __name__ == '__main__':
# Nicely handle closing the server
for sig in (signal.SIGINT, signal.SIGTERM):
signal.signal(sig, clean_resources)
这是我的tornado_supervisor.conf配置文件
[program:tornado_server]
command = python /opt/tornado/server.py -p 8890
user = www-data
stdout_logfile = /var/log/tornado/tornado_server_sup.log
redirect_stderr = true
autorestart=true
environment=HOME='/var/www'
environment=PYTHONPATH="$PYTHONPATH:/opt/tornado/"
stopsignal = TERM
stopwaitsecs = 10
stopasgroup = true
1 个回答
0
我遇到过类似的问题。只有父进程收到了信号,而子进程却没有被杀掉。
我做了一些调整,让父进程手动杀掉子进程,使用了 os.killpg() 这个方法。同时,子进程在被杀之前会有一些延迟,以便(可能)完成当前的请求:
#will be initialized in main()
server = None
loop = None
def stop_loop():
global loop
loop.stop()
def signal_handler_child_callback():
global loop
global server
server.stop()
# allow to finish processing current requests
loop.add_timeout(time.time() + LOOP_STOP_DELAY, stop_loop)
def signal_handler(signum, frame):
global loop
global server
if loop:
#this is child process, will restrict incoming connections and stop ioloop after delay
loop.add_callback(signal_handler_child_callback)
else:
#this is master process, should restrict new incomming connections
#and send signal to child processes
server.stop()
signal.signal(signal.SIGTERM, signal.SIG_DFL)
os.killpg(0, signal.SIGTERM)
def main():
parse_command_line()
signal.signal(signal.SIGTERM, signal_handler)
# ...
tornado_app = tornado.web.Application(
[
#...
])
global server
server = tornado.httpserver.HTTPServer(tornado_app)
server.bind(options.port)
server.start(0)
global loop
loop = tornado.ioloop.IOLoop.instance()
loop.start()
if __name__ == '__main__':
main()