如何在不使用ctrl-c的情况下停止烧瓶应用

时间:2022-01-24 02:54:37

I want to implement a command which can stop flask application by using flask-script. I have searched the solution for a while. Because the framework doesn't provide "app.stop()" API, I am curious about how to code this. I am working on Ubuntu 12.10 and Python 2.7.3.

我想通过使用flask-script来实现一个可以停止烧瓶应用的命令。我已经搜索了一段时间的解决方案。因为框架不提供“app.stop()”API,所以我很好奇如何编写代码。我正在研究Ubuntu 12.10和Python 2.7.3。

5 个解决方案

#1


51  

If you are just running the server on your desktop, you can expose an endpoint to kill the server (read more at 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...'

Here is another approach that is more contained:

这是另一种更加包含的方法:

from multiprocessing import Process

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

Let me know if this helps.

如果这有帮助,请告诉我。

#2


12  

I did it slightly different using threads

我使用线程做的略有不同

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()

I use it to do end to end tests for restful api, where I can send requests using the python requests library.

我使用它来为restful api做端到端测试,我可以使用python请求库发送请求。

#3


5  

My method can be proceeded via bash terminal/console

我的方法可以通过bash终端/控制台进行

1) run and get the process number

1)运行并获取进程号

$ ps aux | grep yourAppKeywords

2a) kill the process

2a)杀死进程

$ kill processNum

2b) kill the process if above not working

2b)如果上面没有工作就杀了这个过程

$ kill -9 processNum

#4


4  

As others have pointed out, you can only use werkzeug.server.shutdown from a request handler. The only way I've found to shut down the server at another time is to send a request to yourself. For example, the /kill handler in this snippet will kill the dev server unless another request comes in during the next second:

正如其他人指出的那样,您只能从请求处理程序中使用werkzeug.server.shutdown。我发现在另一个时间关闭服务器的唯一方法是向自己发送请求。例如,此代码段中的/ kill处理程序将终止开发服务器,除非在下一秒内有另一个请求进入:

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..."

#5


2  

This is an old question, but googling didn't give me any insight in how to accomplish this.

这是一个老问题,但谷歌搜索没有给我任何洞察力如何实现这一目标。

Because I didn't read the code here properly! (Doh!) What it does is to raise a RuntimeError when there is no werkzeug.server.shutdown in the request.environ...

因为我没有在这里正确阅读代码! (Doh!)它的作用是在request.environ中没有werkzeug.server.shutdown时引发RuntimeError ...

So what we can do when there is no request is to raise a RuntimeError

所以当没有请求时我们可以做的是引发RuntimeError

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

and catch that when app.run() returns:

并在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
...

No need to send yourself a request.

无需向您发送请求。

#1


51  

If you are just running the server on your desktop, you can expose an endpoint to kill the server (read more at 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...'

Here is another approach that is more contained:

这是另一种更加包含的方法:

from multiprocessing import Process

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

Let me know if this helps.

如果这有帮助,请告诉我。

#2


12  

I did it slightly different using threads

我使用线程做的略有不同

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()

I use it to do end to end tests for restful api, where I can send requests using the python requests library.

我使用它来为restful api做端到端测试,我可以使用python请求库发送请求。

#3


5  

My method can be proceeded via bash terminal/console

我的方法可以通过bash终端/控制台进行

1) run and get the process number

1)运行并获取进程号

$ ps aux | grep yourAppKeywords

2a) kill the process

2a)杀死进程

$ kill processNum

2b) kill the process if above not working

2b)如果上面没有工作就杀了这个过程

$ kill -9 processNum

#4


4  

As others have pointed out, you can only use werkzeug.server.shutdown from a request handler. The only way I've found to shut down the server at another time is to send a request to yourself. For example, the /kill handler in this snippet will kill the dev server unless another request comes in during the next second:

正如其他人指出的那样,您只能从请求处理程序中使用werkzeug.server.shutdown。我发现在另一个时间关闭服务器的唯一方法是向自己发送请求。例如,此代码段中的/ kill处理程序将终止开发服务器,除非在下一秒内有另一个请求进入:

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..."

#5


2  

This is an old question, but googling didn't give me any insight in how to accomplish this.

这是一个老问题,但谷歌搜索没有给我任何洞察力如何实现这一目标。

Because I didn't read the code here properly! (Doh!) What it does is to raise a RuntimeError when there is no werkzeug.server.shutdown in the request.environ...

因为我没有在这里正确阅读代码! (Doh!)它的作用是在request.environ中没有werkzeug.server.shutdown时引发RuntimeError ...

So what we can do when there is no request is to raise a RuntimeError

所以当没有请求时我们可以做的是引发RuntimeError

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

and catch that when app.run() returns:

并在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
...

No need to send yourself a request.

无需向您发送请求。