Skip to main content
 首页 » 编程设计

python之主管不会杀死 flask 应用程序

2025年05月04日12lvdongjie

我有以下 supervisord 的 conf 文件:

[program:backend] 
command=../../../venv/bin/python backend.py 
 
[program:celeryd] 
command=../../../venv/bin/celery worker --app=tasks -l debug 
 
[program:memcached] 
command=memcached 

我的 backend.py 是一个非常标准的 flask 应用程序,带有 debug=True。它不是守护进程(在控制台中运行 python backend.py 不返回提示)

当我执行 supervisord 时,我看到以下提示:

[venv] supervisor$ supervisord 
2013-05-08 18:42:22,148 INFO RPC interface 'supervisor' initialized 
2013-05-08 18:42:22,148 CRIT Server 'unix_http_server' running without any HTTP authentication checking 
2013-05-08 18:42:22,149 INFO supervisord started with pid 6778 
2013-05-08 18:42:23,152 INFO spawned: 'celeryd' with pid 6781 
2013-05-08 18:42:23,156 INFO spawned: 'memcached' with pid 6782 
2013-05-08 18:42:23,159 INFO spawned: 'backend' with pid 6783 
2013-05-08 18:42:24,314 INFO success: celeryd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 
2013-05-08 18:42:24,314 INFO success: memcached entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 
2013-05-08 18:42:24,314 INFO success: backend entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 

这是 pstree 的样子:

 | | \-+= 91117 vng -/bin/bash 
 | |   \-+= 06778 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/supervisord 
 | |     |-+= 06781 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python ../../../venv/bin/celery worker --app=tasks -l debug 
 | |     | |--- 06795 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python ../../../venv/bin/celery worker --app=tasks -l debug 
 | |     | |--- 06796 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python ../../../venv/bin/celery worker --app=tasks -l debug 
 | |     | |--- 06797 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python ../../../venv/bin/celery worker --app=tasks -l debug 
 | |     | \--- 06798 vng /Volumes/Data2/Dropbox/projects/Giordano/venv/bin/python ../../../venv/bin/celery worker --app=tasks -l debug 
 | |     |--= 06782 vng memcached 
 | |     \-+= 06783 vng ../../../venv/bin/python backend.py 
 | |       \--- 06790 vng /Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/../../../venv/bin/python backend.py 

杀死主管导致:

^C2013-05-08 18:43:18,305 WARN received SIGINT indicating exit request 
2013-05-08 18:43:18,305 INFO waiting for celeryd, memcached, backend to die 
2013-05-08 18:43:18,352 INFO stopped: backend (exit status 0) 
2013-05-08 18:43:18,353 INFO stopped: memcached (terminated by SIGTERM) 
2013-05-08 18:43:18,414 INFO stopped: celeryd (exit status 0) 

不知从何而来,backend.py 在 pstree 中被替换了:

 |--= 41659 root /usr/libexec/taskgated -s 
 |--- 42779 vng /usr/local/Cellar/erlang/R15B03-1/lib/erlang/erts-5.9.3.1/bin/epmd -daemon 
 |--= 88518 root /usr/sbin/ocspd 
 |--- 97815 vng /Applications/Dropbox.app/Contents/MacOS/Dropbox /firstrunupdate 403 
 |--= 97905 _usbmuxd /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/Resources/usbmuxd -launchd 
 \--- 06790 vng /Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/../../../venv/bin/python backend.py 

我对此很恼火,因为每次我重新启动 supervisord 时,我都会收到一个端口已被使用的错误。

这里有谁知道是什么导致了这个问题?

编辑:

我的后端.py

app = Flask(__name__) 
app.config.from_object(__name__) 
app.secret_key = 'asgasdasdgasd' 
app.debug = bool(int(os.environ.get("DEBUG", 1)))   # DEBUG=0 
if app.debug: 
  from giordano.web import colorer # Needed for coloring logging 
 
app.config.update( 
  MAIL_SERVER='smtp.gmail.com', 
  MAIL_DEBUG=False, 
  MAIL_PORT=465, 
  MAIL_USE_SSL=True, 
  MAIL_USERNAME = 'asdfasdfasdfasdfasdf@asdasdfas.com', 
  MAIL_PASSWORD = 'asdfasdfasdfa' 
) 
mail = Mail(app)    # Very important to do it after!! 
 
log_level = logging.DEBUG if app.debug else logging.INFO 
logging.basicConfig(level=log_level, format='%(asctime)s %(levelname)s %(message)s') 
logging.info("Launching app with debug=%s" % app.debug) 
 
.... 
 
class TimedRequestHandler(BaseRequestHandler): 
  """http://blog.sendhub.com/post/48832423565/hacking-flask-a-success-story 
  """ 
  def handle(self): 
    self.fancyStarted = time.time() 
    rv = super(TimedRequestHandler, self).handle() 
    return rv 
 
  def send_response(self, code, message=None): 
    self.fancyProcessed = time.time() 
    super(TimedRequestHandler, self).send_response(code, message=None) 
 
  def log_request(self, code='-', size='-'): 
    duration = int((self.fancyProcessed - self.fancyStarted) * 1000) 
    line = '"{0}" {1} {2} [{3}ms]'.format(self.requestline, code, size, duration) 
    self.log('info', line) 
 
 
if __name__ == "__main__": 
   init_db() # run if you need to create tables 
   app.run(host='0.0.0.0', port=8888, request_handler=TimedRequestHandler) 

请您参考如下方法:

在您的配置中添加 stopasgroup=true,它应该可以工作。当您执行 stop 或 restart 时,此配置将终止所有子进程。

If true, the flag causes supervisor to send the stop signal to the whole process group and implies killasgroup is true. This is useful for programs, such as Flask in debug mode, that do not propagate stop signals to their children, leaving them orphaned. 

http://supervisord.org/configuration.html