如何在系统关机时触发Flask应用发送通知邮件?
最优实现方案
一、Flask应用内监听关机信号
直接在Flask代码中添加信号处理逻辑,捕获系统发送的关机/重启信号(SIGTERM是系统服务停止时的标准信号,SIGINT用于本地测试),触发邮件发送后优雅退出。
步骤1:集成邮件发送功能
用flask-mail简化配置,先安装依赖:
pip install flask-mail
在Flask应用中配置邮箱参数并实现邮件发送函数:
from flask import Flask from flask_mail import Mail, Message import signal import sys app = Flask(__name__) # 替换为你的实际邮箱配置 app.config['MAIL_SERVER'] = 'smtp.example.com' app.config['MAIL_PORT'] = 587 app.config['MAIL_USE_TLS'] = True app.config['MAIL_USERNAME'] = 'your-email@example.com' app.config['MAIL_PASSWORD'] = 'your-app-specific-password' # 用邮箱的应用专用密码,而非登录密码 app.config['MAIL_DEFAULT_SENDER'] = 'your-email@example.com' mail = Mail(app) def send_restart_alert(): """发送服务器重启提醒邮件""" msg = Message( subject='服务器即将重启,Flask应用需手动重启', recipients=['your-notify-email@example.com'] # 替换为接收提醒的邮箱 ) msg.body = """ 注意:服务器即将执行强制系统更新并重启。 重启完成后,请手动登录服务器,重启Flask应用。 """ try: with app.app_context(): mail.send(msg) print("重启提醒邮件已发送") except Exception as e: print(f"发送邮件失败:{str(e)}")
步骤2:注册信号处理函数
添加信号监听,捕获关机信号并触发邮件发送:
def handle_shutdown_signal(signum, frame): """处理关机信号""" print(f"收到信号 {signum},即将发送重启提醒邮件") send_restart_alert() sys.exit(0) # 注册信号处理 signal.signal(signal.SIGTERM, handle_shutdown_signal) signal.signal(signal.SIGINT, handle_shutdown_signal) @app.route('/') def index(): return 'Flask应用运行中' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)
二、系统级兜底方案(避免信号被忽略)
如果系统重启时直接强制杀死进程(比如超时强制终止),Flask的信号处理可能来不及执行。这时候可以用systemd服务脚本,在服务停止前执行独立的邮件发送脚本。
步骤1:编写独立邮件发送脚本(send_alert.py)
抽离邮件逻辑为独立脚本,无需Flask上下文:
import smtplib from email.mime.text import MIMEText def send_restart_alert(): # 替换为你的实际邮箱配置 smtp_server = 'smtp.example.com' smtp_port = 587 username = 'your-email@example.com' password = 'your-app-specific-password' sender = 'your-email@example.com' receiver = 'your-notify-email@example.com' msg = MIMEText(""" 注意:服务器即将执行强制系统更新并重启。 重启完成后,请手动登录服务器,重启Flask应用。 """, 'plain', 'utf-8') msg['Subject'] = '服务器即将重启,Flask应用需手动重启' msg['From'] = sender msg['To'] = receiver try: with smtplib.SMTP(smtp_server, smtp_port) as server: server.starttls() server.login(username, password) server.sendmail(sender, receiver, msg.as_string()) print("重启提醒邮件已发送") except Exception as e: print(f"发送邮件失败:{str(e)}") if __name__ == '__main__': send_restart_alert()
步骤2:配置systemd服务文件
创建/etc/systemd/system/flask-app.service:
[Unit] Description=Flask Application After=network.target [Service] User=your-user # 替换为运行Flask应用的系统用户 WorkingDirectory=/path/to/your/flask/app ExecStart=/usr/bin/python3 app.py ExecStop=/usr/bin/python3 /path/to/send_alert.py # 服务停止时执行邮件脚本 Restart=no # 重启后无法自动登录,关闭自动重启 KillMode=process # 确保先执行ExecStop再终止进程 TimeoutStopSec=30 # 给邮件发送留足够时间 [Install] WantedBy=multi-user.target
重新加载systemd并启动服务:
sudo systemctl daemon-reload sudo systemctl start flask-app sudo systemctl enable flask-app
注意事项
- 邮箱需使用应用专用密码:Gmail、Outlook等邮箱需开启两步验证后生成应用密码,不能用普通登录密码。
- 测试信号触发:可通过
kill -TERM <flask-pid>命令测试信号捕获和邮件发送功能。 - 网络权限:确保服务器防火墙放行SMTP端口(如587),能正常连接邮箱SMTP服务器。
内容的提问来源于stack exchange,提问作者MrPeriodical
相关产品推荐
相关产品推荐

