Cara menghentikan aplikasi labu tanpa menggunakan ctrl-c

104

Saya ingin mengimplementasikan perintah yang dapat menghentikan aplikasi flask dengan menggunakan flask-script. Saya telah mencari solusi untuk sementara waktu. Karena framework tidak menyediakan API "app.stop ()", saya ingin tahu tentang cara membuat kode ini. Saya sedang mengerjakan Ubuntu 12.10 dan Python 2.7.3.

vic
sumber
Mengapa Anda harus dapat menghentikan aplikasi Anda dari skrip? (Alat terbaik untuk pekerjaan itu akan bergantung pada apa yang Anda coba lakukan).
Sean Vieira
Serius, apa yang kamu coba lakukan di sini? Jika Anda berbicara tentang devserver untuk pengembangan, tidak masalah jika Anda menghentikannya seperti itu. Dalam produksi, Anda tidak menerapkan seperti ini dan Anda dapat menghentikan permintaan kapan saja Anda mau, sehingga "aplikasi berhenti berjalan".
Ignas Butėnas
@ SeanVieira Saya ingin tahu apakah ada solusi untuk melakukan ini.
vic
@Rumahguguk. Saya sedang mengembangkan layanan RESTful di komputer saya sekarang. Saya sedang mengerjakan sebuah proyek mungkin itu akan membantu saya untuk memilih mesin mana yang harus saya terapkan. Satu-satunya cara saya dapat mengetahuinya adalah mematikan dengan menghentikan proses.
vic
3
@vrootic, tetapi Anda tidak akan menggunakan app.run () dalam produksi. app.run () hanya digunakan untuk pengembangan dan untuk menguji aplikasi Anda saat mengembangkan. Ada berbagai cara untuk menjalankan Flask dalam produksi, lebih banyak cara dapat ditemukan di sini misalnya flask.pocoo.org/docs/quickstart/#deploying-to-a-web-server Dan jika Anda sudah menerapkannya seperti itu (jadi saya salah paham pertanyaan), cara untuk menghentikan permintaan yang datang ke Flask adalah dengan menghentikan server http yang melayaninya.
Ignas Butėnas

Jawaban:

125

Jika Anda baru saja menjalankan server di desktop Anda, Anda dapat mengekspos titik akhir untuk mematikan server (baca lebih lanjut di 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...'

Berikut adalah pendekatan lain yang lebih berisi:

from multiprocessing import Process

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

Beri tahu saya jika ini membantu.

Zorayr
sumber
16
Apakah Anda tahu jika ada cara untuk mendapatkan properti 'werkzeug.server.shutdown' tanpa memerlukan konteks permintaan?
akatkinson
5
Saya harus mengubah metode rute menjadi 'GET' agar berfungsi.
CS
5
Untuk kelengkapan jawaban ini tidak memiliki fungsi yang akan Anda panggil di luar konteks permintaan untuk melakukan shutdown, yang tidak lebih dari permintaan HTTP ke server (yang dapat berasal dari / ke localhost)
JamesHutchison
1
Dengan methods='POST', saya mendapatkan 405 Method not allowedkesalahan, sedangkan dengan metode = 'GET'`, ini berfungsi seperti yang disarankan @CS.
Agile Bean
1
Tidak berhasil untuk saya di AWS Elastic Beanstalk. Bekerja dengan baik secara lokal
Andrey Bulezyuk
34

Saya melakukannya sedikit berbeda menggunakan utas

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

Saya menggunakannya untuk melakukan tes ujung ke ujung untuk restful api, di mana saya dapat mengirim permintaan menggunakan pustaka permintaan python.

Ruben Decrop
sumber
2
Saya tidak berhasil mendapatkan hal-hal lain untuk berfungsi tetapi solusi ini berfungsi dengan baik! Terima kasih banyak! Untuk orang lain: ini juga bekerja dengan flask restful!
Jorrick Sleijster
Ini tampaknya memblokir di windows sampai saya memukulnya dengan permintaan lain ... dengan cara apa pun?
Claudiu
Saya mengalami masalah yang sama dengan @Claudiu, kecuali di Linux dengan python 3.6.2
micahscopes
Saya tidak tahu mengapa ini tidak diterima, tetapi tampaknya yang terbersih dan berfungsi dengan baik tanpa ketergantungan tambahan. Terima kasih banyak.
Eric Reed
17

Ini adalah utas yang agak lama, tetapi jika seseorang bereksperimen, mempelajari, atau menguji aplikasi flask dasar, dimulai dari skrip yang berjalan di latar belakang, cara tercepat untuk menghentikannya adalah dengan menghentikan proses yang berjalan pada port tempat Anda menjalankan aplikasi Anda di. Catatan: Saya tahu penulis sedang mencari cara untuk tidak mematikan atau menghentikan aplikasi. Tetapi ini dapat membantu seseorang yang sedang belajar.

sudo netstat -tulnp | grep :5001

Anda akan mendapatkan sesuatu seperti ini.

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

Untuk menghentikan aplikasi, matikan prosesnya

sudo kill 28834
RJ
sumber
15

Metode saya dapat dilanjutkan melalui terminal / konsol bash

1) jalankan dan dapatkan nomor proses

$ ps aux | grep yourAppKeywords

2a) menghentikan proses

$ kill processNum

2b) matikan proses jika di atas tidak berfungsi

$ kill -9 processNum
Nam G VU
sumber
9
Saya hampir yakin bahwa pertanyaannya bukanlah "bagaimana cara mematikan suatu proses", dan masalahnya adalah melakukan ctrl + c tidak membunuhnya. Btw, saya menggunakan karena kill -9 `lsof -i:5000 -t`tidak lain dari hanya 1 aplikasi yang dapat menggunakan port dan itu mudah.
m3nda
9

Seperti yang ditunjukkan orang lain, Anda hanya dapat menggunakan werkzeug.server.shutdowndari penangan permintaan. Satu-satunya cara yang saya temukan untuk mematikan server di lain waktu adalah mengirim permintaan kepada diri Anda sendiri. Misalnya, /killpenangan dalam cuplikan ini akan mematikan server dev kecuali ada permintaan lain yang masuk selama detik berikutnya:

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
sumber
2
ini berfungsi tetapi terasa ... sangat hacky. Saya tahu ini sudah lama, tetapi apakah Anda pernah menemukan cara yang bersih untuk melakukan ini, tanpa mengirimkan permintaan kepada diri sendiri?
Berair
7

Ini adalah pertanyaan lama, tetapi googling tidak memberi saya wawasan apa pun tentang cara melakukannya.

Karena saya tidak membaca kode di sini dengan benar! (Doh!) Apa yang dilakukannya adalah menaikkan RuntimeErrorketika tidak ada werkzeug.server.shutdowndi request.environ...

Jadi yang bisa kita lakukan bila tidak ada requestadalah menaikkan aRuntimeError

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

dan tangkap itu ketika app.run()kembali:

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

Tidak perlu mengirim permintaan sendiri.

jogco
sumber
4

Anda tidak perlu menekan "CTRL-C", tetapi Anda dapat memberikan titik akhir yang melakukannya untuk Anda:

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

Sekarang Anda bisa memanggil titik akhir ini untuk mematikan server dengan baik:

curl localhost:5000/stopServer
Deg
sumber
Saya menguji kode Anda, tetapi setelah itu os.kill, tanggapan yang dikembalikan tidak dapat diterima oleh klien. Untuk curl, itu menghasilkan "curl: (56) Terima kegagalan: Sambungan direset". Dapat melihat juga Menjalankan fungsi setelah Flask mengembalikan respon untuk menyelesaikannya.
samm
@samm, kesimpulan dari pertanyaan itu adalah itu tidak mungkin kecuali Anda memulai utas yang berbeda, bukan? Lalu bagaimana Anda mematikan server flask dari thread yang berbeda itu?
Jurgen
3

Anda dapat menggunakan metode di bawah ini

app.do_teardown_appcontext()
Alex
sumber
2

Jika Anda bekerja pada CLI dan hanya memiliki satu termos aplikasi / proses yang berjalan (atau lebih tepatnya, Anda hanya ingin ingin membunuh setiap proses labu berjalan pada sistem Anda), Anda dapat membunuhnya dengan:

kill $(pgrep -f flask)

kip2
sumber
1

Jika Anda berada di luar penanganan permintaan-respons, Anda masih dapat:

import os
import signal

sig = getattr(signal, "SIGKILL", signal.SIGTERM)
os.kill(os.getpid(), sig)
aplikasi publik
sumber
0

Instance Google Cloud VM + Aplikasi Flask

Saya menghosting Aplikasi Flask saya di Mesin Virtual Google Cloud Platform. Saya memulai aplikasi menggunakan python main.pyTetapi masalahnya adalah ctrl + c tidak berfungsi untuk menghentikan server.

Perintah ini $ sudo netstat -tulnp | grep :5000menghentikan server.

Aplikasi Flask saya berjalan pada port 5000 secara default.

Catatan: Instance VM saya berjalan di Linux 9.

Ini berhasil untuk ini. Belum diuji untuk platform lain. Jangan ragu untuk memperbarui atau memberi komentar jika berfungsi untuk versi lain juga.

Rohit Singh
sumber
-1

Untuk Windows, cukup mudah untuk menghentikan / mematikan server flask -

  1. Goto Task Manager
  2. Temukan flask.exe
  3. Pilih dan Akhiri proses
Sumit Bajaj
sumber
10
Tombol daya di komputer Anda juga cukup efektif haha
Michael Green