programing

ctrl-c를 사용하지 않고 플라스크 적용을 중지하는 방법

lovejava 2023. 7. 3. 22:28

ctrl-c를 사용하지 않고 플라스크 적용을 중지하는 방법

플라스크 스크립트를 사용하여 플라스크 적용을 중지할 수 있는 명령을 구현하고 싶습니다.저는 한동안 그 해결책을 찾아보았습니다.프레임워크가 제공하지 않기 때문입니다.app.stop()API, 이것을 어떻게 코딩하는지 궁금합니다.저는 Ubuntu 12.10과 Python 2.7.3에서 일하고 있습니다.

데스크톱에서 서버를 실행하는 경우 엔드포인트를 노출하여 서버를 종료할 수 있습니다(단순 서버 종료에서 자세히 확인).

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.get('/shutdown')
def shutdown():
    shutdown_server()
    return 'Server shutting down...'

다음은 더 많이 포함된 또 다른 접근 방식입니다.

from multiprocessing import Process

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

이게 도움이 된다면 알려주세요.

스레드를 사용하여 약간 다르게 했습니다.

from werkzeug.serving import make_server

class ServerThread(threading.Thread):

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

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

    def shutdown(self):
        self.server.shutdown()

def start_server():
    global server
    app = flask.Flask('myapp')
    # App routes defined here
    server = ServerThread(app)
    server.start()
    log.info('server started')

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

저는 이것을 사용하여 python 요청 라이브러리를 사용하여 요청을 보낼 수 있는 restful api에 대한 엔드 투 엔드 테스트를 수행합니다.

이것은 약간 오래된 스레드이지만, 누군가 기본 플라스크 앱을 실험, 학습 또는 테스트하는 것이 백그라운드에서 실행되는 스크립트에서 시작된 경우 앱을 실행 중인 포트에서 실행 중인 프로세스를 종료하는 것이 가장 빠른 방법입니다.참고: 작성자가 앱을 종료하거나 중지하지 않는 방법을 찾고 있다는 것을 알고 있습니다.하지만 이것은 배우고 있는 누군가에게 도움이 될 수 있습니다.

sudo netstat -tulnp | grep :5001

이런 걸 얻게 될 겁니다.

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

앱을 중지하려면 프로세스 중지

sudo kill 28834

내 방법은 bash 터미널/콘솔을 통해 진행할 수 있습니다.

실행하여 프로세스 번호 가져오기

$ ps aux | grep yourAppKeywords

2a) 프로세스 중단

$ kill processNum

2b) 위에서 작동하지 않을 경우 프로세스 종료

$ kill -9 processNum

했듯이, 은 다른사람이지이오, 은직듯당신만 할 수 .werkzeug.server.shutdown요청 처리자로부터.다른 시간에 서버를 종료할 수 있는 유일한 방법은 자신에게 요청을 보내는 것입니다.를 들면, 를들어예,,/kill는 다음 한 입니다.

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.post('/seriouslykill')
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.post('/kill')
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..."

이것은 오래된 질문이지만, 구글링은 제게 이것을 어떻게 달성할 수 있는지에 대한 통찰력을 주지 못했습니다.

가 여기 코드를 제대로 읽지 못했기 때문에! (도!)그것이 하는 일은 a를 키우는 것입니다.RuntimeError가 때werkzeug.server.shutdown에 시대에request.environ...

그래서 우리가 할 수 있는 것은 없을 때입니다.requesta를 키우는 것입니다.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
...

직접 요청할 필요가 없습니다.

CLI에서 작업 중이고 하나의 플라스크 앱/프로세스만 실행 중인 경우(또는 시스템에서 실행 중인 플라스크 프로세스를 종료하려는 경우) 다음을 사용하여 제거할 수 있습니다.

kill $(pgrep -f flask)

+를 누를 필요는 없지만 엔드포인트를 제공하여 다음 작업을 수행할 수 있습니다.

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

요청-응답 처리 범위 밖에 있는 경우에도 다음 작업을 수행할 수 있습니다.

import os
import signal

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

request.environ.get 비권위의Pavel Minaev 솔루션은 매우 명확합니다.

import os
from flask import Flask


app = Flask(__name__)
exiting = False

@app.route("/exit")
def exit_app():
    global exiting
    exiting = True
    return "Done"

@app.teardown_request
def teardown(exception):
    if exiting:
        os._exit(0)

만약 다른 사람이 win32 서비스 내에서 Flask 서버를 중지하는 방법을 찾고 있다면 - 여기 있습니다.여러 가지 접근 방식을 조합한 것은 좀 이상하지만, 잘 작동합니다.주요 아이디어:

  1. 은 이들은입니다.shutdown정상 종료에 사용할 수 있는 끝점입니다.참고: 다음에 의존합니다.request.environ.get웹 요청의 컨텍스트 내에서만 사용할 수 있습니다(아래 참조)@app.route function -ed 함수)
  2. 32개의 서비스를 획득합니다.SvcStop는 메드사용을 합니다.requests서비스 자체에 대한 HTTP 요청을 수행합니다.

나의 서비스

import win32service
import win32serviceutil
import win32event
import servicemanager
import time
import traceback
import os

import myservice


class MyServiceSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = "MyServiceSvc"                       # NET START/STOP the service by the following name
    _svc_display_name_ = "Display name"  # this text shows up as the service name in the SCM
    _svc_description_ = "Description" # this text shows up as the description in the SCM

    def __init__(self, args):
        os.chdir(os.path.dirname(myservice.__file__))
        win32serviceutil.ServiceFramework.__init__(self, args)

    def SvcDoRun(self):
        # ... some code skipped
        myservice.start()

    def SvcStop(self):
        """Called when we're being shut down"""
        myservice.stop()
        # tell the SCM we're shutting down
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STOPPED,
                              (self._svc_name_, ''))

if __name__ == '__main__':
    os.chdir(os.path.dirname(myservice.__file__))
    win32serviceutil.HandleCommandLine(MyServiceSvc)

나의 봉사파이의

from flask import Flask, request, jsonify

# Workaround - otherwise doesn't work in windows service.
cli = sys.modules['flask.cli']
cli.show_server_banner = lambda *x: None

app = Flask('MyService')

# ... business logic endpoints are skipped.

@app.route("/shutdown", methods=['GET'])
def shutdown():
    shutdown_func = request.environ.get('werkzeug.server.shutdown')
    if shutdown_func is None:
        raise RuntimeError('Not running werkzeug')
    shutdown_func()
    return "Shutting down..."


def start():
    app.run(host='0.0.0.0', threaded=True, port=5001)


def stop():
    import requests
    resp = requests.get('http://0.0.0.0:5001/shutdown')

Python 솔루션

방법: 행실대:python kill_server.py.

이것은 Windows 전용입니다.netstat과 함께 수집된 PID로 태스크킬을 수행하여 서버를 종료합니다.

# kill_server.py

import os
import subprocess
import re

port = 5000
host = '127.0.0.1'
cmd_newlines = r'\r\n'

host_port = host + ':' + str(port)
pid_regex = re.compile(r'[0-9]+$')

netstat = subprocess.run(['netstat', '-n', '-a', '-o'], stdout=subprocess.PIPE)  
# Doesn't return correct PID info without precisely these flags
netstat = str(netstat)
lines = netstat.split(cmd_newlines)

for line in lines:
    if host_port in line:
        pid = pid_regex.findall(line)
        if pid:
            pid = pid[0]
            os.system('taskkill /F /PID ' + str(pid))
        
# And finally delete the .pyc cache
os.system('del /S *.pyc')

favicon/index.html loading(예: 이전 버전이 캐시됨)에 대한 변경사항으로 문제가 있다면 Chrome에서도 "Clear Browsing Data > Images & Files"를 사용해 보십시오.

위의 모든 것들을 하면서, 저는 마침내 플라스크 앱을 실행할 때 제가 좋아하는 아이콘을 얻었습니다.

다음과 같이 자신의 PID를 죽이는 것이 효과가 있다는 것을 발견했습니다.

import os
from flask import Flask

app = Flask(__name__)
own_pid = os.getpid() # Get the main process's PID in a global variable

@app.route('/kill-backend')
def kill_backend():
    global own_pid # Make sure to use the global variable
    os.kill(own_pid, 9) # The second argument is the signal, 9 stands for SIGKILL.
#If you want to "politely ask" the server to quit you can use SIGQUIT (15) instead.

app.run(host='0.0.0.0', port=8000)

Ubuntu 22.04 LTS와 Window $10에서 테스트했습니다.둘 다 효과가 있습니다.

서버 킬을 트리거하려면 요청하십시오.http://127.0.0.1/kill-backend그리고 그것은 실패하고 실패할 것입니다.connection refused서버가 즉시 중지되었기 때문에 오류가 발생했습니다.

아래의 방법을 사용할 수 있습니다.

app.do_teardown_appcontext()

Google Cloud VM 인스턴스 + 플라스크 앱

Google Cloud Platform Virtual Machine 플라스크는 구글 클라우드 플랫폼 가상 머신입니다.는 나는앱시다니습했작을▁using를 사용하여 했습니다.python main.py그러나 문제는 ctrl+c가 서버를 중지할 수 없다는 것입니다.

명령어는 다음과 같습니다.$ sudo netstat -tulnp | grep :5000서버를 종료합니다.

내 플라스크 앱은 기본적으로 포트 5000에서 실행됩니다.

참고: 내 VM 인스턴스가 Linux 9에서 실행되고 있습니다.

이것에 효과가 있습니다.다른 플랫폼은 테스트하지 않았습니다.다른 버전에서도 작동한다면 언제든지 업데이트하거나 의견을 제시하십시오.

app = MyFlaskSubclass()

...

app.httpd = MyWSGIServerSubclass()

...
 
@app.route('/shutdown')
def app_shutdown():
    from threading import Timer
    t = Timer(5, app.httpd.shutdown)
    t.start()
    return "Server shut down"

My bash 스크립트 변형(LINUX):

#!/bin/bash
portFind="$1"
echo "Finding process on port: $portFind"
pid=$(netstat -tulnp | grep :"$1" | awk '{print $7}' | cut -f1 -d"/")
echo "Process found: $pid"
kill -9 $pid
echo "Process $pid killed"

사용 예:

sudo bash killWebServer.sh 2223

출력:

Finding process on port: 2223
Process found: 12706
Process 12706 killed

포트가 알려진 경우(예: 5000) 간단한 해결 방법은 다음과 같습니다.

fuser -k 5000/tcp

그러면 포트 5000의 프로세스가 중지됩니다.

Linux에서 특정 포트에서 실행 중인 프로세스를 종료하는 방법은 무엇입니까?

가 werkzeug라는 것입니다.BaseWSGIServer에 의해 생성된 인스턴스werkzeug.serving.run_simple()(이 이름은app.run())에 액세스할 수 없습니다.하지만 이 클래스는 클린을 정의합니다.shutdown()해킹 없이 서버의 주 루프를 효과적으로 종료하는 방법입니다.

그래서 우리가 그 인스턴스에 접근할 수 있다면 서버를 죽일 수 있습니다.제가 생각할 수 있는 한 가지 방법은 쓰레기 수집가의 객체 추적입니다.

@app.route("/shutdown", methods=["POST"])
def shutdown():
    for obj in gc.get_objects():
        try:
            if isinstance(obj, BaseWSGIServer):
                obj.shutdown()
                return "bye"
        except:
            pass
    return "failed"

저는 유닛 테스트에서 POST 콜백을 만드는 것을 모방하기 위해 이것이 필요하다는 것을 알게 되었습니다.이 기능을 사용하면 플라스크 서버를 스레드로 실행할 수 있으며 다른 테스트를 실행하는 동안에도 서버가 계속 작동할 걱정을 하지 않습니다.

Windows의 경우 플라스크 서버를 중지/제거하는 것이 매우 쉽습니다.

  1. 작업 관리자로 이동
  2. 플라스크를 찾습니다.exe
  3. 프로세스 선택 및 종료

언급URL : https://stackoverflow.com/questions/15562446/how-to-stop-flask-application-without-using-ctrl-c