提交
This commit is contained in:
1 parent
34a843e790
commit
abfc5cd746
14 files changed
+1595
-1148
No files matched your search
Executable
+252
@@ -0,0 +1,252 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生状态变更处理脚本 - 复学 (修复版本)
|
||||
# 处理类型: FU_XUE(复学)
|
||||
# ===========================================
|
||||
|
||||
# set -euo pipefail # Temporarily disable to prevent script exit on errors
|
||||
|
||||
# Force C locale to ensure consistent behavior across systems
|
||||
export LANG=C
|
||||
export LC_ALL=C
|
||||
|
||||
# Load configuration
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONFIG_FILE="${SCRIPT_DIR}/data.conf"
|
||||
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
# Create log directory
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Log file
|
||||
LOG_FILE="${LOG_DIR}/process_student_resume_fixed_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# Lock file to prevent multiple instances
|
||||
LOCK_FILE="${SCRIPT_DIR}/process_student_resume_fixed.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
|
||||
}
|
||||
|
||||
# Database functions - Fixed version
|
||||
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执行失败: $sql"
|
||||
log "ERROR" "MySQL错误: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
# Database query function - Fixed version for cross-platform compatibility
|
||||
execute_query() {
|
||||
local sql="$1"
|
||||
local result
|
||||
|
||||
# Use -ss for ultra-silent mode to ensure clean tab-separated output
|
||||
# Redirect stderr to /dev/null to discard warnings, only capture actual data
|
||||
result=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" -ss "$DB_NAME" -e "$sql" 2>/dev/null)
|
||||
local exit_code=$?
|
||||
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
log "ERROR" "查询执行失败: $sql"
|
||||
log "ERROR" "MySQL错误码: $exit_code"
|
||||
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}"
|
||||
|
||||
# Validate input parameters
|
||||
if [[ -z "$record_id" || -z "$student_id" || -z "$student_no" || -z "$change_type" ]]; then
|
||||
log "ERROR" "参数不完整 - record_id: '$record_id', student_id: '$student_id', student_no: '$student_no', change_type: '$change_type'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "INFO" "正在处理学生复学 - ID: $record_id, 学生: $student_no ($student_id), 类型: $change_type"
|
||||
|
||||
# Start transaction
|
||||
local transaction_sql="
|
||||
START TRANSACTION;
|
||||
|
||||
-- 1. Backup original data to his tables (ignore if already exists)
|
||||
INSERT IGNORE INTO xg_student_msg_his SELECT * FROM xg_student_msg WHERE id = $student_id;
|
||||
INSERT IGNORE 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 = '1',
|
||||
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 (using execute_sql to allow error output for debugging)
|
||||
if execute_sql "$transaction_sql"; then
|
||||
log "INFO" "成功处理学生复学 - ID: $record_id, 学生: $student_no"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "处理学生复学失败 - ID: $record_id, 学生: $student_no"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
log "INFO" "启动学生复学处理守护进程 (修复版本)"
|
||||
log "INFO" "处理类型: FU_XUE(复学)"
|
||||
log "INFO" "以连续模式运行,间隔10分钟"
|
||||
|
||||
# 测试数据库连接
|
||||
log "INFO" "正在测试数据库连接..."
|
||||
if ! execute_sql "SELECT 1;" >/dev/null 2>&1; then
|
||||
error_exit "数据库连接失败"
|
||||
fi
|
||||
log "INFO" "数据库连接成功"
|
||||
|
||||
# Main processing loop
|
||||
while true; do
|
||||
log "INFO" "开始新的复学处理周期"
|
||||
|
||||
# 获取未处理的记录
|
||||
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
|
||||
AND effective_date <= NOW()
|
||||
ORDER BY create_time ASC
|
||||
LIMIT $BATCH_SIZE;
|
||||
"
|
||||
|
||||
local records
|
||||
records=$(execute_query "$query_sql")
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
log "ERROR" "获取待处理记录失败"
|
||||
sleep $CYCLE_INTERVAL
|
||||
continue
|
||||
fi
|
||||
|
||||
# 检查是否有记录需要处理(过滤掉空行和MySQL警告信息)
|
||||
local clean_records
|
||||
clean_records=$(echo "$records" | grep -v "^mysql:" | grep -v "^$" | wc -l)
|
||||
|
||||
if [[ $clean_records -eq 0 ]]; then
|
||||
log "INFO" "未找到未处理的复学记录,正在等待..."
|
||||
else
|
||||
log "INFO" "找到 $clean_records 条待处理复学记录"
|
||||
|
||||
local processed_count=0
|
||||
local failed_count=0
|
||||
|
||||
# Process records directly from the query result, skip header and empty lines
|
||||
local is_first_line=true
|
||||
while IFS=$'\t' read -r record_id student_id student_no change_type operator_id; do
|
||||
# Skip completely empty lines
|
||||
[[ -z "$record_id$student_id$student_no$change_type$operator_id" ]] && continue
|
||||
|
||||
# Skip header line (first non-empty line that looks like column names)
|
||||
if [[ $is_first_line == true ]]; then
|
||||
is_first_line=false
|
||||
# Check if this looks like a header line
|
||||
if [[ "$record_id" == "id" || "$record_id" =~ ^[[:space:]]*id[[:space:]]*$ ]]; then
|
||||
log "INFO" "跳过标题行"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Validate required fields
|
||||
if [[ -z "$record_id" || -z "$student_id" || -z "$student_no" || -z "$change_type" ]]; then
|
||||
log "WARN" "跳过无效记录 - ID: '$record_id', 学生ID: '$student_id', 学号: '$student_no', 类型: '$change_type'"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Log the record being processed for debugging
|
||||
log "INFO" "读取到复学记录 - ID: $record_id, 学生ID: $student_id, 学号: $student_no, 类型: $change_type, 操作员: ${operator_id:-1}"
|
||||
|
||||
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" "处理失败,$RETRY_DELAY 秒后重试... (尝试 $retry_count/$MAX_RETRY)"
|
||||
sleep $RETRY_DELAY
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $success == false ]]; then
|
||||
((failed_count++))
|
||||
log "ERROR" "$MAX_RETRY 次尝试后仍处理失败 - ID: $record_id"
|
||||
fi
|
||||
|
||||
done <<< "$(echo "$records" | grep -v "^mysql:" | grep -v "^$")"
|
||||
|
||||
log "INFO" "复学处理周期完成 - 已处理: $processed_count, 失败: $failed_count"
|
||||
fi
|
||||
|
||||
# 等待配置的间隔时间后开始下一个周期
|
||||
log "INFO" "等待 $CYCLE_INTERVAL 秒后开始下一个复学处理周期..."
|
||||
sleep $CYCLE_INTERVAL
|
||||
done
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
Reference in new issue
Block a user