2013-03-22 61 views
35

我想實現一個可以通過使用瓶子腳本來停止瓶應用的命令。 我已經搜索了一段時間的解決方案。由於該框架不提供「app.stop()」API,我很好奇如何對此進行編碼。我正在使用Ubuntu 12.10和Python 2.7.3。如何在不使用ctrl-c的情況下停止瓶的應用

+0

爲什麼你需要能夠停止腳本中的應用程序? (這項工作的最佳工具將取決於你想要做什麼)。 – 2013-03-22 05:14:51

+0

說真的,你想在這裏做什麼?如果您正在談論devserver進行開發,那麼停止它就完全沒問題。在生產中,您不會像這樣部署,您可以隨時停止請求,因此「應用程序停止運行」。 – 2013-03-22 05:42:45

+0

@SeanVieira我想知道是否有任何解決方案來做到這一點。 – vrootic 2013-03-22 08:51:01

回答

44

如果你只是運行桌面上的服務器,你可以公開端點殺死服務器(更在Shutdown The Simple Server讀):

from flask import request 
def shutdown_server(): 
    func = request.environ.get('werkzeug.server.shutdown') 
    if func is None: 
     raise RuntimeError('Not running with the Werkzeug Server') 
    func() 

@app.route('/shutdown', methods=['POST']) 
def shutdown(): 
    shutdown_server() 
    return 'Server shutting down...' 

這裏是另一種方法是多個內含:

from multiprocessing import Process 

server = Process(target=app.run) 
server.start() 
# ... 
server.terminate() 
server.join() 

讓我知道這是否有幫助。

+8

您是否知道是否有任何方法可以在不需要請求上下文的情況下獲得'werkzeug.server.shutdown'屬性? – akatkinson 2014-10-13 04:31:06

+1

我不得不將路由方法更改爲「GET」才能使其工作。 – 2016-08-31 20:39:26

+2

爲了完整起見,這個答案是缺少你要在請求上下文之外調用關閉的函數,這不過是對服務器的HTTP請求(可以源於/到本地主機) – JamesHutchison 2017-03-04 00:59:52

4

正如其他人指出的那樣,您只能從請求處理程序中使用werkzeug.server.shutdown。我發現在另一時間關閉服務器的唯一方法是向您發送請求。

import requests 
from threading import Timer 
import time 

LAST_REQUEST_MS = 0 
@app.before_request 
def update_last_request_ms(): 
    global LAST_REQUEST_MS 
    LAST_REQUEST_MS = time.time() * 1000 


@app.route('/seriouslykill', methods=['POST']) 
def seriouslykill(): 
    func = request.environ.get('werkzeug.server.shutdown') 
    if func is None: 
     raise RuntimeError('Not running with the Werkzeug Server') 
    func() 
    return "Shutting down..." 


@app.route('/kill', methods=['POST']) 
def kill(): 
    last_ms = LAST_REQUEST_MS 
    def shutdown(): 
     if LAST_REQUEST_MS <= last_ms: # subsequent requests abort shutdown 
      requests.post('http://localhost:5000/seriouslykill') 
     else: 
      pass 

    Timer(1.0, shutdown).start() # wait 1 second 
    return "Shutting down..." 
+0

這個工作,但感覺.. _very_ hacky。我知道這已經有一段時間了,但是你有沒有找到一個乾淨的方式來做到這一點,而不向自己發送請求? – Juicy 2017-05-28 20:35:50

2

我的方法可通過bash的終端/主機可以進行

1)運行,並得到:例如,除非另一個請求在下一第二進來的/kill處理程序在這個片段將殺死dev的服務器進程號

$ ps aux | grep yourAppKeywords 

2a)的殺進程

$ kill processNum 

圖2b),如果以上不工作

$ kill -9 processNum 
+0

我幾乎可以肯定,問題不是「如何殺死一個進程」,問題是做ctrl + c不會殺死它。順便說一句,我確實使用'kill -9 \'lsof -i:5000 -t''cuz除了1個應用程序可以使用該端口並且非常簡單外, – erm3nda 2017-03-29 07:12:31

2

這是一個老問題,但谷歌搜索沒有給我如何做到這一點任何見解殺死進程。

因爲我沒有正確閱讀code here! (DOH!) 它的作用是提高RuntimeError時,有在request.environ沒有werkzeug.server.shutdown ...

那麼,什麼時候沒有request我們可以做的是提高RuntimeError

def shutdown(): 
    raise RuntimeError("Server going down") 

並在app.run()返回時發現:

... 
try: 
    app.run(host="0.0.0.0") 
except RuntimeError, msg: 
    if str(msg) == "Server going down": 
     pass # or whatever you want to do when the server goes down 
    else: 
     # appropriate handling/logging of other runtime errors 
# and so on 
... 

無需發送自己的請求。

7

我做到了使用線程略有不同

from werkzeug.serving import make_server 

class ServerThread(threading.Thread): 

    def __init__(self, app): 
     threading.Thread.__init__(self) 
     self.srv = make_server('127.0.0.1', 5000, app) 
     self.ctx = app.app_context() 
     self.ctx.push() 

    def run(self): 
     log.info('starting server') 
     self.srv.serve_forever() 

    def shutdown(self): 
     self.srv.shutdown() 

def start_server(): 
    global server 
    app = flask.Flask('myapp') 
    ... 
    server = ServerThread(app) 
    server.start() 
    log.info('server started') 

def stop_server(): 
    global server 
    server.shutdown() 

我用它做端到端的RESTful API,因此在這裏我可以給使用Python請求庫請求測試。

+0

我沒有設法讓其他東西工作,但這種解決方案效果很好!萬分感謝!對於其他人:它也適用於燒瓶安寧! – 2017-09-04 14:38:59

+0

這似乎阻止在窗戶上,直到我用另一個請求打...它以任何方式? – Claudiu 2017-10-12 19:45:41

+0

我和@Claudiu的問題一樣,除了使用python 3.6.2的Linux – micahscopes 2017-11-19 00:23:09

相關問題