python - 如果服务器被 CTRL+C 杀死或中断或崩溃,则执行操作
问题描述
我有一个不断运行的应用程序(在 Linux 中启动,screen -S myapp python3 app.py
然后将其分离)。它可以是一个 Bottle 应用程序、Flask 应用程序或任何其他涉及永久运行事件循环的系统:
import anyframework # can be bottle, flask or anything else
import sqlite3
@route('/')
def index():
c = db.cursor()
c.execute('INSERT INTO test VALUES (?)', ('test',))
c.close() # we can't commit here for *each* client request, it would eat 100ms for each request
return 'hello'
@route('/makeitcrash')
def index():
sdlfksdfs # this will generate an error
def cleanup():
db.commit()
db = sqlite3.connect('test.db')
run()
如何确保cleanup()
在服务器终止的所有可能情况下可靠地调用(以及因此 DB 提交)?IE:
如果服务器被 SIGKILL 杀死,SIGTERM
如果服务器代码有错误(例如,如果访问http://example.com/makeitcrash)
如果我在终端中执行CTRL+ C(在运行中
screen
)
?
我正要在任何地方使用atexit
和添加try: except:
,但我认为它会引入许多代码重复以插入try: except:
每条路线。
这个问题的一般解决方案是什么?
解决方案
一种方法是捕获信号并在收到信号时进行清理。
import signal
import sys
from bottle import run
def handle_signal(signum, frame):
print(f'handling signal {signum}')
# do cleanup
sys.exit(0)
signal.signal(signal.SIGINT, handle_signal)
# also SIGTERM, et al.
run()
注意事项
正如@MarkAllen 指出的那样,SIGKILL
永远不会被抓住。
我也建议不要首先以这种方式解决问题。相反,看看您是否可以设计您的 Web 应用程序,使其在关闭时不需要进行任何清理。(例如,对每个请求执行持久写入,而不是在内存中缓冲。)减少您保留的状态量将有助于简化许多事情,包括如何处理崩溃/关闭。
推荐阅读
- javascript - 为什么 Ajax $.post() 函数返回数据
? - java - 初始化时继承的类变量会覆盖父级设置的自己的值
- perforce - Perforce 流复制想要删除文件
- android - Android - Mockito 无法模拟此类:class android.content.Context
- python - Scrapy不返回元素
- c# - Linq 可以在正则表达式替换之前检查值是否为 Null
- php - 设置 session_id 参数时请求 404
- linux - Bash 脚本 SSH 命令变量插值
- python - 如何在 docker run 期间将来自 k8s 的 ENV 变量提供给 python 应用程序
- webrtc - 如何防止 JsSIP 要求麦克风访问?