ctrl-cを使用せずにフラスコアプリケーションを停止する方法


102

フラスコスクリプトを使用してフラスコアプリケーションを停止できるコマンドを実装したい。しばらくの間、解決策を探しました。フレームワークは "app.stop()" APIを提供しないので、これをコード化する方法に興味があります。私はUbuntu 12.10とPython 2.7.3に取り組んでいます。


スクリプトからアプリケーションを停止できる必要があるのはなぜですか?(仕事に最適なツールは、何をしようとしているかによって異なります)。
Sean Vieira

真剣に、ここで何をしようとしていますか?開発用のdevserverについて話している場合は、そのように停止しても問題ありません。本番環境ではこのようにデプロイせず、いつでもリクエストを停止できるため、「アプリの実行が停止します」。
IgnasButėnas2013年

@SeanVieira私はこれを行うための解決策があるかどうか知りたいです。
vic

@IgnasB。現在、マシンでRESTfulサービスを開発しています。私はプロジェクトに取り組んでいるので、展開するマシンを選択するのに役立つかもしれません。
vic

3
@vrootic、しかしとにかく本番環境ではapp.run()を使用しません。app.run()は、開発と、開発中にアプリケーションをテストするためにのみ使用されます。運用環境で Flaskを実行する方法はいくつかあります。たとえば、ここではフラスコ.pocoo.org / docs / quickstart /#deploying-to-a-web-serverのように展開できます。質問)、Flaskへのリクエストの提供を停止する方法は、それを提供しているhttpサーバーを停止することです。
IgnasButėnas2013年

回答:


121

デスクトップでサーバーを実行しているだけの場合は、エンドポイントを公開してサーバーを強制終了することができます(詳細については、「単純なサーバーのシャットダウン」を参照してください)。

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

これが役立つかどうかを教えてください。


15
リクエストコンテキストを必要とせずに 'werkzeug.server.shutdown'プロパティを取得する方法があるかどうかをご存知ですか?
akatkinson、2014年

5
routeメソッドを「GET」に変更して機能させる必要がありました。
CS

5
完全を
期す

1
を使用するmethods='POST'と、405 Method not allowedエラーが発生しますが、methods = 'GET'`を使用すると、@ CSの提案どおりに機能します。
アジャイルBean

1
AWS Elastic Beanstalkでは動作しませんでした。ローカルでうまくいった
Andrey Bulezyuk '31 / 07/31

34

スレッドを使って少し違った

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リクエストライブラリを使用してリクエストを送信できます。


2
他の機能をうまく動作させることができませんでしたが、このソリューションはうまく機能します!トンありがとう!他の人々のために:それはまた、休息フラスコで動作します!
Jorrick Sleijster 2017

これは、別のリクエストでヒットするまで、ウィンドウをブロックしているようです...それを回避する方法はありますか?
Claudiu

私は、Python 3.6.2でLinux上を除き、@Claudiuと同じ問題を抱えている
micahscopes

これが受け入れられない理由はわかりませんが、これは最もクリーンで、余分な依存関係がなくても問題なく動作するようです。本当にありがとう。
エリックリード

17

これは少し古いスレッドですが、誰かが基本的なフラスコアプリを実験、学習、またはテストしていて、バックグラウンドで実行されるスクリプトから開始した場合、それを停止する最も早い方法は、アプリを実行しているポートで実行されているプロセスを強制終了することですオン。注:私は作成者がアプリを強制終了または停止しない方法を探していることを認識しています。しかし、これは学習している人を助けるかもしれません。

sudo netstat -tulnp | grep :5001

このようなものが得られます。

tcp 0 0 0.0.0.0:5001 0.0.0.0:* LISTEN 28834 / python

アプリを停止するには、プロセスを終了します

sudo kill 28834

14

私の方法はbashターミナル/コンソールで続行できます

1)実行してプロセス番号を取得する

$ ps aux | grep yourAppKeywords

2a)プロセスを終了する

$ kill processNum

2b)上記が機能しない場合は、プロセスを強制終了します

$ kill -9 processNum

9
問題は「プロセスを強制終了する方法」ではなく、ctrl + cを実行しても強制終了されないことが問題であると私はほぼ確信しています。ところで、私はkill -9 `lsof -i:5000 -t`cuzを使用していますが、1つのアプリでしかポートを使用できず、簡単です。
m3nda 2017年

9

他の人が指摘したように、werkzeug.server.shutdownリクエストハンドラからのみ使用できます。後でサーバーをシャットダウンする唯一の方法は、自分にリクエストを送信することです。たとえば/kill、このスニペットのハンドラーは、次の1秒間に別のリクエストが来ない限り、開発サーバーを強制終了します。

import requests
from threading import Timer
from flask import request
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..."

2
これは機能しますが、非常にハッキーです。久しぶりだと思いますが、自分にリクエストを送ることなく、これを行うきれいな方法を見つけたことがありますか?
ジューシーな

7

これは古い質問ですが、グーグルでこれを達成する方法についての洞察は得られませんでした。

ここコードを正しく読んでいないからです!(ドー!)何もないRuntimeErrorときにレイズするのwerkzeug.server.shutdownrequest.environ...

だから、私たちができないときにできることはrequestRuntimeError

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

自分でリクエストを送信する必要はありません。


4

"CTRL-C"を押す必要はありませんが、それを行うエンドポイントを提供することができます:

from flask import Flask, jsonify, request
import json, os, signal

@app.route('/stopServer', methods=['GET'])
def stopServer():
    os.kill(os.getpid(), signal.SIGINT)
    return jsonify({ "success": True, "message": "Server is shutting down..." })

これで、このエンドポイントを呼び出してサーバーを正常にシャットダウンできます。

curl localhost:5000/stopServer

コードをテストしましたが、の後os.kill、返された応答をクライアントが受信できません。の場合curl、「curl:(56)Recv failure:Connection was reset」と出力されます。また、表示される場合がありフラスコが応答を返した後、機能を実行し、それを解決するために。
SAMM

@samm、その質問からの結論は、別のスレッドを開始しない限り不可能だということですよね?次に、その別のスレッドからフラスコサーバーをどのようにシャットダウンしますか?
ジャージー


2

あなたがしてCLIで作業している場合にのみ実行されている1つのフラスコアプリ/プロセスを持っている(というか、あなただけ殺したいたいすべてのあなたがそれを殺すことができ、あなたのシステム上で実行されているフラスコのプロセスを):

kill $(pgrep -f flask)


1

リクエスト/レスポンス処理の範囲外の場合でも、次のことができます。

import os
import signal

sig = getattr(signal, "SIGKILL", signal.SIGTERM)
os.kill(os.getpid(), sig)

1

Google Cloud VMインスタンス+ Flaskアプリ

FlaskアプリケーションをGoogle Cloud Platform Virtual Machineでホストしました。私はアプリを使い始めましたがpython main.py、問題はctrl + cがサーバーを停止するように機能しないことでした。

このコマンド$ sudo netstat -tulnp | grep :5000はサーバーを終了します。

私のFlaskアプリはデフォルトでポート5000で実行されます。

注:VMインスタンスはLinux 9で実行されています。

これでうまくいきます。他のプラットフォームではテストしていません。他のバージョンでも機能する場合は、更新またはコメントしてください。


-1

Windowsの場合、フラスコサーバーを停止/終了するのは非常に簡単です-

  1. タスクマネージャーに移動
  2. フラスコ.exeを見つける
  3. プロセスを選択して終了

9
コンピューターの電源ボタンも非常に効果的です
マイケルグリーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.