feat: 添加信号处理,记录进程被kill的来源信息
This commit is contained in:
57
app.py
57
app.py
@@ -9,6 +9,7 @@ import json
|
|||||||
import subprocess
|
import subprocess
|
||||||
import signal
|
import signal
|
||||||
import threading
|
import threading
|
||||||
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import Flask, render_template_string, jsonify, request
|
from flask import Flask, render_template_string, jsonify, request
|
||||||
import urllib.request
|
import urllib.request
|
||||||
@@ -20,11 +21,58 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|||||||
WORKSPACE_DIR = os.path.dirname(BASE_DIR) # works目录
|
WORKSPACE_DIR = os.path.dirname(BASE_DIR) # works目录
|
||||||
ROOT_DIR = os.path.dirname(WORKSPACE_DIR) # workspace-coder目录
|
ROOT_DIR = os.path.dirname(WORKSPACE_DIR) # workspace-coder目录
|
||||||
PROJECTS_FILE = os.path.join(BASE_DIR, 'projects.json')
|
PROJECTS_FILE = os.path.join(BASE_DIR, 'projects.json')
|
||||||
|
LOG_FILE = os.path.join(BASE_DIR, 'logs', 'app.log')
|
||||||
|
|
||||||
# 进程状态缓存
|
# 进程状态缓存
|
||||||
process_cache = {}
|
process_cache = {}
|
||||||
|
|
||||||
|
|
||||||
|
def log_message(msg):
|
||||||
|
"""写入日志"""
|
||||||
|
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
log_line = f"[{timestamp}] {msg}\n"
|
||||||
|
# 同时输出到控制台和日志文件
|
||||||
|
print(log_line.strip())
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
|
||||||
|
with open(LOG_FILE, 'a') as f:
|
||||||
|
f.write(log_line)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def signal_handler(signum, frame):
|
||||||
|
"""处理信号,记录kill来源"""
|
||||||
|
signal_names = {
|
||||||
|
signal.SIGTERM: 'SIGTERM',
|
||||||
|
signal.SIGINT: 'SIGINT',
|
||||||
|
signal.SIGHUP: 'SIGHUP',
|
||||||
|
}
|
||||||
|
sig_name = signal_names.get(signum, f'SIGNAL_{signum}')
|
||||||
|
|
||||||
|
# 尝试获取kill来源
|
||||||
|
try:
|
||||||
|
import psutil
|
||||||
|
proc = psutil.Process()
|
||||||
|
parent = proc.parent()
|
||||||
|
parent_info = f"父进程: {parent.pid} ({parent.name()})"
|
||||||
|
except:
|
||||||
|
parent_info = "无法获取父进程信息"
|
||||||
|
|
||||||
|
log_message(f"⚠️ 进程收到 {sig_name} 信号,即将退出! {parent_info}")
|
||||||
|
log_message(f"信号来源可能是: 手动kill命令、systemd、OOM killer、或其他进程")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
# 注册信号处理
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGHUP, signal_handler)
|
||||||
|
except:
|
||||||
|
pass # Windows不支持SIGHUP
|
||||||
|
|
||||||
|
|
||||||
def load_projects():
|
def load_projects():
|
||||||
"""加载项目配置"""
|
"""加载项目配置"""
|
||||||
with open(PROJECTS_FILE, 'r', encoding='utf-8') as f:
|
with open(PROJECTS_FILE, 'r', encoding='utf-8') as f:
|
||||||
@@ -1322,8 +1370,9 @@ def api_crons():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
os.makedirs(os.path.join(BASE_DIR, 'logs'), exist_ok=True)
|
os.makedirs(os.path.join(BASE_DIR, 'logs'), exist_ok=True)
|
||||||
print("=" * 50)
|
log_message("=" * 50)
|
||||||
print("项目服务管理面板")
|
log_message("项目服务管理面板启动")
|
||||||
print("访问地址: http://localhost:19013")
|
log_message("访问地址: http://localhost:19013")
|
||||||
print("=" * 50)
|
log_message(f"进程PID: {os.getpid()}")
|
||||||
|
log_message("=" * 50)
|
||||||
app.run(host='0.0.0.0', port=19013, debug=False)
|
app.run(host='0.0.0.0', port=19013, debug=False)
|
||||||
Reference in New Issue
Block a user