So stoppen Sie die Kolbenanwendung ohne Strg-C

101

Ich möchte einen Befehl implementieren, der die Kolbenanwendung mithilfe des Kolbenskripts stoppen kann. Ich habe eine Weile nach der Lösung gesucht. Da das Framework keine "app.stop ()" - API bereitstellt, bin ich gespannt, wie dies codiert werden kann. Ich arbeite an Ubuntu 12.10 und Python 2.7.3.

vic
quelle
Warum müssen Sie in der Lage sein, Ihre Anwendung über ein Skript zu stoppen? (Das beste Werkzeug für den Job hängt davon ab, was Sie versuchen).
Sean Vieira
Ernsthaft, was versuchst du hier zu tun? Wenn Sie über Devserver für die Entwicklung sprechen, ist es vollkommen in Ordnung, dies so zu stoppen. In der Produktion stellen Sie diese nicht so bereit und können eine Anforderung jederzeit stoppen, sodass die "App nicht mehr ausgeführt wird".
Ignas Butėnas
@ SeanVieira Ich möchte wissen, ob es dafür Lösungen gibt.
Vic
@IgnasB. Ich entwickle gerade einen RESTful-Service auf meinem Computer. Ich arbeite an einem Projekt. Vielleicht hilft es mir bei der Auswahl der Computer, die ich bereitstellen soll. Der einzige Weg, den ich herausfinden kann, ist das Herunterfahren, indem der Prozess abgebrochen wird.
Vic
3
@vrootic, aber Sie werden app.run () sowieso nicht in der Produktion verwenden. app.run () wird nur zur Entwicklung und zum Testen Ihrer Anwendung während der Entwicklung verwendet. Es gibt verschiedene Möglichkeiten, Flask in der Produktion auszuführen. Weitere finden Sie hier, zum Beispiel flask.pocoo.org/docs/quickstart/#deploying-to-a-web-server. Und wenn Sie bereits so etwas bereitstellen (also habe ich es falsch verstanden Frage), um die Zustellung von Anfragen an Flask zu beenden, müssen Sie den http-Server stoppen, der sie bedient.
Ignas Butėnas

Antworten:

119

Wenn Sie den Server nur auf Ihrem Desktop ausführen, können Sie einen Endpunkt zum Beenden des Servers verfügbar machen (weitere Informationen finden Sie unter Herunterfahren des einfachen Servers ):

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

Hier ist ein anderer Ansatz, der ausführlicher ist:

from multiprocessing import Process

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

Lassen Sie mich wissen, ob das hilft.

Zorayr
quelle
15
Wissen Sie, ob es eine Möglichkeit gibt, die Eigenschaft 'werkzeug.server.shutdown' abzurufen, ohne einen Anforderungskontext zu benötigen?
Akatkinson
5
Ich musste die Routenmethode auf 'GET' ändern, damit es funktioniert.
CS
5
Der Vollständigkeit halber fehlt dieser Antwort die Funktion, die Sie außerhalb eines Anforderungskontexts aufrufen würden, um das Herunterfahren
durchzuführen. Dies
1
Mit methods='POST'erhalte ich eine 405 Method not allowedFehlermeldung, während es mit Methoden = 'GET'` wie von @CS vorgeschlagen funktioniert.
Agile Bean
1
Hat bei AWS Elastic Beanstalk nicht funktioniert. Arbeitete gut vor Ort
Andrey Bulezyuk
34

Ich habe es mit Threads etwas anders gemacht

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

Ich verwende es, um End-to-End-Tests für eine erholsame API durchzuführen, bei denen ich Anforderungen mithilfe der Python-Anforderungsbibliothek senden kann.

Ruben Decrop
quelle
2
Ich habe es nicht geschafft, die anderen Dinge zum Laufen zu bringen, aber diese Lösung funktioniert großartig! Danke vielmals! Für die anderen Leute: Es funktioniert auch mit Flasche erholsam!
Jorrick Sleijster
Dies scheint Windows zu blockieren, bis ich es mit einer anderen Anfrage getroffen habe ... irgendwie um das herum?
Claudiu
Ich habe das gleiche Problem wie @Claudiu, außer unter Linux mit Python 3.6.2
Micahscopes
Ich weiß nicht, warum dies nicht akzeptiert wird, aber es scheint das sauberste zu sein und funktioniert ohne zusätzliche Abhängigkeiten hervorragend. Vielen Dank.
Eric Reed
17

Dies ist ein etwas alter Thread, aber wenn jemand, der experimentiert, lernt oder die grundlegende Flask-App testet, von einem Skript gestartet wurde, das im Hintergrund ausgeführt wird, können Sie ihn am schnellsten stoppen, indem Sie den Prozess beenden, der auf dem Port ausgeführt wird, auf dem Sie Ihre App ausführen auf. Hinweis: Mir ist bekannt, dass der Autor nach einer Möglichkeit sucht, die App nicht zu beenden oder zu stoppen. Aber dies kann jemandem helfen, der lernt.

sudo netstat -tulnp | grep :5001

Sie werden so etwas bekommen.

tcp 0 0 0.0.0.0:5001 0.0.0.0:* HÖREN 28834 / Python

Beenden Sie den Vorgang, um die App zu stoppen

sudo kill 28834
RJ
quelle
14

Meine Methode kann über das Bash-Terminal / die Bash-Konsole fortgesetzt werden

1) ausführen und die Prozessnummer abrufen

$ ps aux | grep yourAppKeywords

2a) Beenden Sie den Prozess

$ kill processNum

2b) Beenden Sie den Prozess, wenn oben nicht funktioniert

$ kill -9 processNum
Nam G VU
quelle
9
Ich bin mir fast sicher, dass die Frage nicht "wie man einen Prozess beendet" ist, und das Problem ist, dass Strg + C ihn nicht beendet. kill -9 `lsof -i:5000 -t`Übrigens benutze ich, weil keine andere als nur 1 App den Port nutzen kann und einfach ist.
m3nda
9

Wie andere bereits erwähnt haben, können Sie nur werkzeug.server.shutdowneinen Anforderungshandler verwenden. Die einzige Möglichkeit, den Server zu einem anderen Zeitpunkt herunterzufahren, besteht darin, eine Anfrage an sich selbst zu senden. Der /killHandler in diesem Snippet beendet beispielsweise den Entwicklungsserver, sofern in der nächsten Sekunde keine weitere Anforderung eingeht:

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..."
danvk
quelle
2
das funktioniert aber fühlt sich ... sehr hackig an. Ich weiß, es ist schon eine Weile her, aber haben Sie jemals einen sauberen Weg gefunden, dies zu tun, ohne eine Anfrage an sich selbst zu senden?
Saftig
7

Dies ist eine alte Frage, aber das Googeln gab mir keinen Einblick, wie ich das erreichen kann.

Weil ich den Code hier nicht richtig gelesen habe ! (Doh!) Was es tut, ist ein zu erhöhen, RuntimeErrorwenn es keine werkzeug.server.shutdownin der request.environ...

Was wir also tun können, wenn es kein requestgibt, ist, a zu erhöhenRuntimeError

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

und fangen Sie das bei der app.run()Rückkehr:

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

Sie müssen sich keine Anfrage senden.

jogco
quelle
4

Sie müssen nicht "STRG-C" drücken, sondern können einen Endpunkt angeben, der dies für Sie erledigt:

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

Jetzt können Sie diesen Endpunkt einfach aufrufen, um den Server ordnungsgemäß herunterzufahren:

curl localhost:5000/stopServer
Deg
quelle
Ich habe Ihren Code getestet, aber danach os.killkann der Kunde die zurückgegebene Antwort nicht mehr empfangen. Für curlgibt es "curl: (56) Recv-Fehler: Verbindung wurde zurückgesetzt" aus. Siehe auch kann eine Funktion nach Flask kehrt Reaktion ausführen , es zu lösen.
Samm
@samm, die Schlussfolgerung aus dieser Frage ist, dass es nur möglich ist, wenn Sie einen anderen Thread starten, oder? Wie können Sie dann den Flask-Server von diesem anderen Thread herunterfahren?
Jurgy
3

Sie können die folgende Methode verwenden

app.do_teardown_appcontext()
Alex
quelle
2

Wenn Sie auf der CLI arbeiten und haben nur einen Kolben app / Prozess läuft (oder besser gesagt, wollen Sie wollen einfach nur töten jeden Kolben - Prozess auf dem System ausgeführt wird ), können Sie es mit töten:

kill $(pgrep -f flask)

kip2
quelle
1

Wenn Sie sich außerhalb der Anfrage-Antwort-Behandlung befinden, können Sie dennoch:

import os
import signal

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

Google Cloud VM-Instanz + Flask App

Ich habe meine Flask-Anwendung auf der virtuellen Maschine der Google Cloud Platform gehostet. Ich habe die App mit gestartet. Das python main.pyProblem war jedoch, dass Strg + C nicht funktioniert hat, um den Server zu stoppen.

Dieser Befehl $ sudo netstat -tulnp | grep :5000beendet den Server.

Meine Flask-App wird standardmäßig auf Port 5000 ausgeführt.

Hinweis: Mein GCP läuft unter Linux 9.

Es funktioniert dafür. Nicht für andere Plattformen getestet. Fühlen Sie sich frei zu aktualisieren oder zu kommentieren, wenn es auch für andere Versionen funktioniert.

Rohit Singh
quelle
-1

Für Windows ist es ziemlich einfach, den Flaschenserver zu stoppen / zu beenden -

  1. Gehe zum Task-Manager
  2. Finden Sie flask.exe
  3. Prozess auswählen und beenden
Sumit Bajaj
quelle
7
Der Netzschalter auf Ihrem Computer ist ebenfalls sehr effektiv, haha
Michael Green