123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #!/bin/bash
- # Delta中性交易策略自动重启脚本
- # 监控并自动重启交易进程
- # 配置
- MAX_RESTARTS=100 # 最大重启次数
- RESTART_DELAY=10 # 重启延迟(秒)
- LOG_FILE="logs/auto-restart.log"
- PID_FILE="trading.pid"
- HEALTH_CHECK_INTERVAL=30 # 健康检查间隔(秒)
- MAX_NO_OUTPUT_TIME=300 # 最大无输出时间(秒)
- # 颜色定义
- RED='\033[0;31m'
- GREEN='\033[0;32m'
- YELLOW='\033[1;33m'
- NC='\033[0m' # No Color
- # 创建日志目录
- mkdir -p logs
- # 日志函数
- log() {
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
- }
- # 启动交易程序
- start_trading() {
- log "🚀 启动交易程序..."
- # 运行交易程序并捕获PID
- yarn trade > logs/trading.log 2>&1 &
- local pid=$!
- echo $pid > "$PID_FILE"
- log "✅ 交易程序已启动 (PID: $pid)"
- return $pid
- }
- # 检查进程是否存活
- check_process() {
- local pid=$1
- if kill -0 $pid 2>/dev/null; then
- return 0
- else
- return 1
- fi
- }
- # 检查日志文件是否有新输出
- check_log_activity() {
- local log_file="logs/trading.log"
- if [ ! -f "$log_file" ]; then
- return 1
- fi
- # 获取文件最后修改时间
- local last_modified=$(stat -f %m "$log_file" 2>/dev/null || stat -c %Y "$log_file" 2>/dev/null)
- local current_time=$(date +%s)
- local time_diff=$((current_time - last_modified))
- if [ $time_diff -gt $MAX_NO_OUTPUT_TIME ]; then
- log "⚠️ 交易程序超过${MAX_NO_OUTPUT_TIME}秒无输出"
- return 1
- fi
- return 0
- }
- # 优雅关闭进程
- graceful_shutdown() {
- local pid=$1
- log "🛑 正在优雅关闭进程 (PID: $pid)..."
- # 发送SIGTERM信号
- kill -TERM $pid 2>/dev/null
- # 等待进程退出(最多10秒)
- local count=0
- while [ $count -lt 10 ]; do
- if ! check_process $pid; then
- log "✅ 进程已优雅关闭"
- return 0
- fi
- sleep 1
- count=$((count + 1))
- done
- # 强制结束
- log "⚠️ 强制结束进程"
- kill -9 $pid 2>/dev/null
- sleep 2
- return 0
- }
- # 清理函数
- cleanup() {
- log "🧹 清理资源..."
- if [ -f "$PID_FILE" ]; then
- local pid=$(cat "$PID_FILE")
- if check_process $pid; then
- graceful_shutdown $pid
- fi
- rm -f "$PID_FILE"
- fi
- log "👋 自动重启脚本退出"
- exit 0
- }
- # 捕获退出信号
- trap cleanup SIGINT SIGTERM
- # 主循环
- main() {
- log "==================================="
- log "🤖 Delta中性交易自动重启脚本启动"
- log "==================================="
- log "最大重启次数: $MAX_RESTARTS"
- log "重启延迟: ${RESTART_DELAY}秒"
- log "健康检查间隔: ${HEALTH_CHECK_INTERVAL}秒"
- log ""
- local restart_count=0
- local consecutive_failures=0
- while [ $restart_count -lt $MAX_RESTARTS ]; do
- # 启动交易程序
- start_trading
- local trading_pid=$!
- # 重置连续失败计数
- if [ $consecutive_failures -gt 0 ]; then
- consecutive_failures=0
- log "✅ 重置连续失败计数"
- fi
- # 监控进程
- while true; do
- sleep $HEALTH_CHECK_INTERVAL
- # 检查进程是否存活
- if ! check_process $trading_pid; then
- log "❌ 进程已停止,准备重启..."
- restart_count=$((restart_count + 1))
- consecutive_failures=$((consecutive_failures + 1))
- # 检查连续失败次数
- if [ $consecutive_failures -ge 5 ]; then
- log "🚨 连续失败5次,延长重启等待时间至60秒"
- sleep 60
- consecutive_failures=0
- else
- sleep $RESTART_DELAY
- fi
- break
- fi
- # 检查日志活动
- if ! check_log_activity; then
- log "⚠️ 进程可能卡死,准备重启..."
- graceful_shutdown $trading_pid
- restart_count=$((restart_count + 1))
- consecutive_failures=$((consecutive_failures + 1))
- sleep $RESTART_DELAY
- break
- fi
- # 显示状态
- echo -ne "\r[$(date '+%H:%M:%S')] 🟢 交易程序运行中 (PID: $trading_pid) | 重启次数: $restart_count/$MAX_RESTARTS"
- done
- log "📊 重启统计: $restart_count/$MAX_RESTARTS"
- done
- log "🚨 达到最大重启次数,脚本退出"
- cleanup
- }
- # 检查是否已有实例在运行
- if [ -f "$PID_FILE" ]; then
- old_pid=$(cat "$PID_FILE")
- if check_process $old_pid; then
- echo -e "${RED}⚠️ 交易程序已在运行 (PID: $old_pid)${NC}"
- echo "如需重新启动,请先运行: kill $old_pid"
- exit 1
- else
- rm -f "$PID_FILE"
- fi
- fi
- # 运行主函数
- main
|