#!/bin/bash # =========================================== # 学生状态变更处理脚本 - 复学 # 处理类型: FU_XUE(复学) # =========================================== set -euo pipefail # Load configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" CONFIG_FILE="${SCRIPT_DIR}/data.conf" if [[ ! -f "$CONFIG_FILE" ]]; then echo "Error: Configuration file $CONFIG_FILE not found!" exit 1 fi source "$CONFIG_FILE" # Create log directory mkdir -p "$LOG_DIR" # Log file LOG_FILE="${LOG_DIR}/process_student_resume_$(date +%Y%m%d_%H%M%S).log" # Lock file to prevent multiple instances LOCK_FILE="${SCRIPT_DIR}/process_student_resume.lock" # Functions log() { local level="$1" local message="$2" local timestamp=$(date '+%Y-%m-%d %H:%M:%S') echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE" } error_exit() { local message="$1" log "ERROR" "$message" # Remove lock file [[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE" exit 1 } # Check if script is already running if [[ -f "$LOCK_FILE" ]]; then if kill -0 $(cat "$LOCK_FILE") 2>/dev/null; then log "INFO" "Script is already running (PID: $(cat "$LOCK_FILE"))" exit 1 else log "WARN" "Removing stale lock file" rm -f "$LOCK_FILE" fi fi # Create lock file echo $$ > "$LOCK_FILE" # Cleanup function cleanup() { [[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE" log "INFO" "Script execution completed" } trap cleanup EXIT # Database functions execute_sql() { local sql="$1" local result result=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$sql" 2>&1) local exit_code=$? if [[ $exit_code -ne 0 ]]; then log "ERROR" "SQL execution failed: $sql" log "ERROR" "MySQL error: $result" return 1 fi echo "$result" } # Process student resume process_student_resume() { local record_id="$1" local student_id="$2" local student_no="$3" local change_type="$4" local operator_id="${5:-1}" log "INFO" "Processing student resume - ID: $record_id, Student: $student_no ($student_id), Type: $change_type" # Start transaction local transaction_sql=" START TRANSACTION; -- 1. Backup original data to his tables INSERT INTO xg_student_msg_his SELECT * FROM xg_student_msg WHERE id = $student_id; INSERT INTO sys_user_his SELECT * FROM sys_user WHERE user_id = $student_id; -- 2. Update student status to resume (复学) UPDATE xg_student_msg SET student_status = '3', update_by = $operator_id, update_time = NOW() WHERE id = $student_id; -- 3. Enable user account UPDATE sys_user SET status = '0', update_by = $operator_id, update_time = NOW() WHERE user_id = $student_id AND account_type = '2'; -- 4. Update change record status UPDATE xg_student_status_change SET process_status = 1, update_by = $operator_id, update_time = NOW() WHERE id = $record_id; COMMIT; " # Execute transaction if execute_sql "$transaction_sql"; then log "INFO" "Successfully processed student resume - ID: $record_id, Student: $student_no" return 0 else log "ERROR" "Failed to process student resume - ID: $record_id, Student: $student_no" return 1 fi } # Main function main() { log "INFO" "Starting student resume processing daemon" log "INFO" "Processing type: FU_XUE(复学)" log "INFO" "Running in continuous mode with 10-minute intervals" # Test database connection log "INFO" "Testing database connection..." if ! execute_sql "SELECT 1;" >/dev/null 2>&1; then error_exit "Database connection failed" fi log "INFO" "Database connection successful" # Main processing loop while true; do log "INFO" "Starting new resume processing cycle" # Get unprocessed records local query_sql=" SELECT id, student_id, student_no, change_type, operator_id FROM xg_student_status_change WHERE process_status = 0 AND change_type = 'FU_XUE' AND deleted = 0 ORDER BY create_time ASC LIMIT $BATCH_SIZE; " local records records=$(execute_sql "$query_sql") # Check if there are records to process local record_count record_count=$(echo "$records" | wc -l) if [[ $record_count -le 1 ]]; then log "INFO" "No unprocessed resume records found, waiting..." else # Remove header line records=$(echo "$records" | tail -n +2) local processed_count=0 local failed_count=0 # Process each record while IFS=$'\t' read -r record_id student_id student_no change_type operator_id; do # Skip empty lines [[ -z "$record_id" ]] && continue local retry_count=0 local success=false while [[ $retry_count -lt $MAX_RETRY && $success == false ]]; do if process_student_resume "$record_id" "$student_id" "$student_no" "$change_type" "$operator_id"; then success=true ((processed_count++)) else ((retry_count++)) if [[ $retry_count -lt $MAX_RETRY ]]; then log "WARN" "Processing failed, retrying in $RETRY_DELAY seconds... (attempt $retry_count/$MAX_RETRY)" sleep $RETRY_DELAY fi fi done if [[ $success == false ]]; then ((failed_count++)) log "ERROR" "Failed to process record after $MAX_RETRY attempts - ID: $record_id" fi done <<< "$records" log "INFO" "Resume processing cycle completed - Processed: $processed_count, Failed: $failed_count" fi # Wait for configured interval before next cycle log "INFO" "Waiting $CYCLE_INTERVAL seconds before next resume processing cycle..." sleep $CYCLE_INTERVAL done } # Run main function main "$@"