#!/bin/bash # =========================================== # 学生状态变更处理服务健康检查脚本 # 用于监控服务运行状态和数据库连接 # =========================================== set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONFIG_FILE="${SCRIPT_DIR}/data.conf" CONTROL_SCRIPT="${SCRIPT_DIR}/control_scripts.sh" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Load configuration if [[ ! -f "$CONFIG_FILE" ]]; then echo -e "${RED}错误:配置文件 $CONFIG_FILE 未找到!${NC}" exit 1 fi source "$CONFIG_FILE" # Functions log() { local level="$1" local message="$2" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo -e "${timestamp} [$level] $message" } success() { echo -e "${GREEN}✓ $1${NC}" } error() { echo -e "${RED}✗ $1${NC}" } warning() { echo -e "${YELLOW}⚠ $1${NC}" } info() { echo -e "${BLUE}ℹ $1${NC}" } # 检查数据库连接 check_database() { info "正在检查数据库连接..." local db_test if db_test=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1 as test;" 2>/dev/null); then if echo "$db_test" | grep -q "test"; then success "数据库连接成功" return 0 else error "数据库查询失败" return 1 fi else error "数据库连接失败" return 1 fi } # 检查服务状态 check_service() { local service_name="$1" local service_desc="$2" info "正在检查 $service_desc..." if [[ ! -x "$CONTROL_SCRIPT" ]]; then error "控制脚本未找到或不可执行: $CONTROL_SCRIPT" return 1 fi local status_output status_output=$("$CONTROL_SCRIPT" status "$service_name" 2>/dev/null) if echo "$status_output" | grep -q "is running"; then success "$service_desc 正在运行" # 提取PID(如果可用) local pid pid=$(echo "$status_output" | grep -o "PID: [0-9]*" | cut -d' ' -f2) if [[ -n "$pid" ]]; then info " 进程ID: $pid" fi return 0 else error "$service_desc 未运行" return 1 fi } # 检查日志文件 check_logs() { info "正在检查日志文件..." if [[ ! -d "$LOG_DIR" ]]; then warning "日志目录不存在: $LOG_DIR" return 1 fi # 统计日志文件数量 local log_count log_count=$(find "$LOG_DIR" -name "*.log" -type f | wc -l) if [[ $log_count -gt 0 ]]; then success "发现 $log_count 个日志文件" # 检查最近的错误 local recent_errors recent_errors=$(find "$LOG_DIR" -name "*.log" -type f -mmin -60 -exec grep -l "ERROR" {} \; | wc -l) if [[ $recent_errors -gt 0 ]]; then warning "发现 $recent_errors 个日志文件包含最近的错误 (最近60分钟)" else info "日志文件中未发现最近的错误" fi return 0 else warning "未发现日志文件" return 1 fi } # 检查待处理记录 check_pending_records() { info "正在检查数据库中的待处理记录..." local pending_changes pending_resume # Check changes (XIU_XUE, TUI_XUE, BI_YE) pending_changes=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e " SELECT COUNT(*) as count FROM xg_student_status_change WHERE process_status = 0 AND change_type IN ('XIU_XUE', 'TUI_XUE', 'BI_YE') AND deleted = 0; " 2>/dev/null | tail -n1) # Check resume (FU_XUE) pending_resume=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e " SELECT COUNT(*) as count FROM xg_student_status_change WHERE process_status = 0 AND change_type = 'FU_XUE' AND deleted = 0; " 2>/dev/null | tail -n1) # Remove potential header pending_changes=$(echo "$pending_changes" | grep -E '^[0-9]+$') pending_resume=$(echo "$pending_resume" | grep -E '^[0-9]+$') if [[ -z "$pending_changes" ]]; then pending_changes="0" fi if [[ -z "$pending_resume" ]]; then pending_resume="0" fi local total_pending=$((pending_changes + pending_resume)) if [[ $total_pending -gt 0 ]]; then info "发现 $total_pending 条待处理记录 ($pending_changes 条变更, $pending_resume 条复学)" if [[ $pending_changes -gt 0 ]]; then warning " $pending_changes 条记录等待变更处理" fi if [[ $pending_resume -gt 0 ]]; then warning " $pending_resume 条记录等待复学处理" fi else success "未发现待处理记录" fi return 0 } # 检查磁盘空间 check_disk_space() { info "正在检查磁盘空间..." local log_disk_usage log_disk_usage=$(df "$LOG_DIR" 2>/dev/null | tail -n1 | awk '{print $5}' | sed 's/%//') if [[ -z "$log_disk_usage" ]]; then warning "无法确定日志目录的磁盘使用情况" return 1 fi if [[ $log_disk_usage -gt 90 ]]; then error "日志目录磁盘使用率达到 ${log_disk_usage}% - 建议清理旧日志" return 1 elif [[ $log_disk_usage -gt 75 ]]; then warning "日志目录磁盘使用率达到 ${log_disk_usage}%" else success "日志目录磁盘使用率 ${log_disk_usage}%" fi return 0 } # Generate health report generate_report() { local report_file="${LOG_DIR}/health_check_$(date +%Y%m%d_%H%M%S).log" { echo "=== 学生状态变更处理服务健康检查报告 ===" echo "检查时间: $(date)" echo "检查主机: $(hostname)" echo "" echo "=== 数据库连接检查 ===" if check_database; then echo "状态: 正常" else echo "状态: 异常" fi echo "" echo "=== 服务状态检查 ===" echo "学生状态变更处理服务 (休学/退学/毕业):" if check_service "changes" "学生状态变更处理服务"; then echo "状态: 运行中" else echo "状态: 未运行" fi echo "学生复学处理服务:" if check_service "resume" "学生复学处理服务"; then echo "状态: 运行中" else echo "状态: 未运行" fi echo "" echo "=== 待处理记录检查 ===" check_pending_records echo "" echo "=== 日志文件检查 ===" check_logs echo "" echo "=== 磁盘空间检查 ===" check_disk_space echo "" echo "=== 配置信息 ===" echo "数据库主机: $DB_HOST:$DB_PORT" echo "数据库名称: $DB_NAME" echo "日志目录: $LOG_DIR" echo "脚本目录: $SCRIPT_DIR" echo "" echo "报告生成完成" } > "$report_file" 2>/dev/null if [[ -f "$report_file" ]]; then success "健康检查报告已生成: $report_file" else error "生成健康检查报告失败" fi } # Main function main() { local generate_report="${1:-false}" echo "" echo "========================================" echo " 学生状态变更处理服务健康检查" echo "========================================" echo "" # Perform all checks check_database echo "" check_service "changes" "学生状态变更处理服务 (休学/退学/毕业)" check_service "resume" "学生复学处理服务" echo "" check_pending_records echo "" check_logs echo "" check_disk_space echo "" # Generate report if requested if [[ "$generate_report" == "report" ]]; then generate_report fi echo "" echo "========================================" success "健康检查完成" echo "" if [[ "$generate_report" == "report" ]]; then echo "详细报告已保存到日志目录" fi echo "使用方法:" echo " $0 # 执行健康检查" echo " $0 report # 执行检查并生成报告" echo "" } # 显示使用方法 show_usage() { cat << EOF 用法: $0 [report] 执行学生状态变更处理服务的健康检查。 选项: report 生成详细的健康检查报告 检查内容: - 数据库连接状态 - 服务运行状态 - 待处理记录数量 - 日志文件状态 - 磁盘空间使用情况 EOF } # Parse arguments case "${1:-}" in report) main "report" ;; -h|--help) show_usage ;; "") main ;; *) error "未知选项: $1" show_usage exit 1 ;; esac