process_student_id_card_refresh.sh 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #!/bin/bash
  2. # ===========================================
  3. # 学生学籍号刷新脚本 v1.0.2
  4. # 处理类型: ID_CARD_REFRESH(学籍号刷新)
  5. # 刷新规则: ext_field2 = 'G' + id_card
  6. # 优化: 直接UPDATE + ROW_COUNT(),无需预查询
  7. # 新增: 支持run_refresh.sh bg模式后台执行
  8. # ===========================================
  9. set -euo pipefail
  10. # Load configuration
  11. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  12. CONFIG_FILE="${SCRIPT_DIR}/data.conf.prod"
  13. if [[ ! -f "$CONFIG_FILE" ]]; then
  14. echo "错误:配置文件 $CONFIG_FILE 未找到!"
  15. exit 1
  16. fi
  17. source "$CONFIG_FILE"
  18. # Create log directory
  19. mkdir -p "$LOG_DIR"
  20. # Log file
  21. LOG_FILE="${LOG_DIR}/process_student_id_card_refresh_$(date +%Y%m%d_%H%M%S).log"
  22. # Lock file to prevent multiple instances
  23. LOCK_FILE="${SCRIPT_DIR}/process_student_id_card_refresh.lock"
  24. # Functions
  25. log() {
  26. local level="$1"
  27. local message="$2"
  28. local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
  29. echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
  30. }
  31. error_exit() {
  32. local message="$1"
  33. log "ERROR" "$message"
  34. # Remove lock file
  35. [[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE"
  36. exit 1
  37. }
  38. # 检查脚本是否已在运行
  39. if [[ -f "$LOCK_FILE" ]]; then
  40. if kill -0 $(cat "$LOCK_FILE") 2>/dev/null; then
  41. log "INFO" "脚本已在运行 (PID: $(cat "$LOCK_FILE"))"
  42. exit 1
  43. else
  44. log "WARN" "删除过期的锁定文件"
  45. rm -f "$LOCK_FILE"
  46. fi
  47. fi
  48. # Create lock file
  49. echo $$ > "$LOCK_FILE"
  50. # 清理函数
  51. cleanup() {
  52. [[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE"
  53. log "INFO" "脚本执行完成"
  54. }
  55. trap cleanup EXIT
  56. # Database functions
  57. execute_sql() {
  58. local sql="$1"
  59. local result
  60. result=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "$sql" 2>&1)
  61. local exit_code=$?
  62. if [[ $exit_code -ne 0 ]]; then
  63. log "ERROR" "SQL执行失败: $sql"
  64. log "ERROR" "MySQL错误: $result"
  65. return 1
  66. fi
  67. echo "$result"
  68. }
  69. # Process student ID card refresh in batch
  70. process_id_card_refresh_batch() {
  71. local batch_offset="$1"
  72. local batch_size="$2"
  73. log "INFO" "开始处理学籍号刷新批次 - 偏移量: $batch_offset, 批次大小: $batch_size"
  74. # 查找需要刷新的学生记录(ext_field2为空或空字符串,且id_card不为空)
  75. local find_records_sql="
  76. SELECT id, student_no, student_name, id_card, ext_field2
  77. FROM xg_student_msg
  78. WHERE (ext_field2 IS NULL OR ext_field2 = '')
  79. AND id_card IS NOT NULL
  80. AND id_card != ''
  81. AND deleted = 0
  82. ORDER BY id ASC
  83. LIMIT $batch_offset, $batch_size;
  84. "
  85. local records
  86. records=$(execute_sql "$find_records_sql")
  87. # 检查是否有记录需要处理
  88. local data_records
  89. data_records=$(echo "$records" | grep -E '^[0-9]' || true)
  90. if [[ -z "$data_records" ]]; then
  91. log "INFO" "未找到需要刷新的学生记录"
  92. return 0
  93. fi
  94. log "INFO" "找到需要刷新的学生记录,开始处理..."
  95. local processed_count=0
  96. local failed_count=0
  97. local student_ids=""
  98. # 收集需要更新的学生ID
  99. while IFS=$'\t' read -r student_id student_no student_name id_card current_ext_field2; do
  100. # Skip empty lines
  101. [[ -z "$student_id" ]] && continue
  102. # 生成新的学籍号:'G' + id_card
  103. local new_id_card="'G$id_card'"
  104. # 构建学生ID列表,用于批量更新
  105. if [[ -z "$student_ids" ]]; then
  106. student_ids="$student_id"
  107. else
  108. student_ids="$student_ids,$student_id"
  109. fi
  110. log "INFO" "准备刷新学籍号 - 学生ID: $student_id, 学号: $student_no, 姓名: $student_name, 身份证: $id_card, 新学籍号: G$id_card"
  111. ((processed_count++))
  112. # 单个更新(为了记录详细日志)
  113. local update_sql="
  114. UPDATE xg_student_msg SET
  115. ext_field2 = 'G$id_card',
  116. update_by = 1,
  117. update_time = NOW()
  118. WHERE id = $student_id AND deleted = 0;
  119. "
  120. if execute_sql "$update_sql"; then
  121. log "INFO" "成功刷新学籍号 - 学生ID: $student_id, 学号: $student_no, 新学籍号: G$id_card"
  122. else
  123. log "ERROR" "刷新学籍号失败 - 学生ID: $student_id, 学号: $student_no"
  124. ((failed_count++))
  125. fi
  126. done <<< "$data_records"
  127. log "INFO" "批次处理完成 - 找到记录: $processed_count, 失败: $failed_count"
  128. # 返回成功处理的记录数
  129. echo $((processed_count - failed_count))
  130. }
  131. # 一次性刷新所有符合条件的学籍号
  132. process_all_id_card_refresh() {
  133. log "INFO" "开始一次性刷新所有学籍号"
  134. # 直接执行批量更新,并获取受影响的行数
  135. local update_sql="
  136. UPDATE xg_student_msg SET
  137. ext_field2 = CONCAT('G', id_card),
  138. update_by = 1,
  139. update_time = NOW()
  140. WHERE (ext_field2 IS NULL OR ext_field2 = '')
  141. AND id_card IS NOT NULL
  142. AND id_card != ''
  143. AND deleted = 0;
  144. SELECT ROW_COUNT() as affected_rows;
  145. "
  146. local update_result
  147. update_result=$(execute_sql "$update_sql")
  148. if [[ $? -eq 0 ]]; then
  149. # 从结果中提取受影响的行数
  150. local affected_rows
  151. affected_rows=$(echo "$update_result" | grep -E '^[0-9]' | awk '{print $1}' | tail -1)
  152. if [[ "$affected_rows" -eq 0 ]]; then
  153. log "INFO" "没有需要刷新的学籍号记录"
  154. else
  155. log "INFO" "学籍号刷新完成 - 成功更新: $affected_rows 条记录"
  156. fi
  157. return 0
  158. else
  159. log "ERROR" "学籍号刷新失败"
  160. return 1
  161. fi
  162. }
  163. # Main function
  164. main() {
  165. log "INFO" "启动学生学籍号刷新处理脚本"
  166. log "INFO" "处理类型: ID_CARD_REFRESH(学籍号刷新)"
  167. log "INFO" "刷新规则: ext_field2 = 'G' + id_card"
  168. # 测试数据库连接
  169. log "INFO" "正在测试数据库连接..."
  170. if ! execute_sql "SELECT 1;" >/dev/null 2>&1; then
  171. error_exit "数据库连接失败"
  172. fi
  173. log "INFO" "数据库连接成功"
  174. # 检查命令行参数
  175. if [[ $# -gt 0 && "$1" == "once" ]]; then
  176. log "INFO" "执行一次性刷新模式"
  177. if process_all_id_card_refresh; then
  178. log "INFO" "一次性刷新完成"
  179. else
  180. error_exit "一次性刷新失败"
  181. fi
  182. else
  183. log "INFO" "执行循环监控模式,间隔10分钟"
  184. # Main processing loop
  185. while true; do
  186. log "INFO" "开始新的处理周期"
  187. # 直接执行批量刷新,如果有记录需要处理就会更新,没有则不影响
  188. if process_all_id_card_refresh; then
  189. log "INFO" "本轮处理周期完成"
  190. else
  191. log "WARN" "本轮处理周期出现错误,将继续下一轮"
  192. fi
  193. # 等待配置的间隔时间后开始下一个周期
  194. log "INFO" "等待 $CYCLE_INTERVAL 秒后开始下一个处理周期..."
  195. sleep $CYCLE_INTERVAL
  196. done
  197. fi
  198. }
  199. # Run main function
  200. main "$@"