提交
This commit is contained in:
1 parent
ff1228873c
commit
34a843e790
23 files changed
+1541
-718
No files matched your search
+1
-1
@@ -66,7 +66,7 @@ public interface XgStudentMsgMapper extends BaseMapperPlus<XgStudentMsg, XgStude
|
||||
* @param studentId 学生ID
|
||||
* @return 学院ID
|
||||
*/
|
||||
Long selectCollegeIdByStudentId(@Param("studentId") Long studentId);
|
||||
String selectCollegeIdByStudentId(@Param("studentId") Long studentId);
|
||||
|
||||
/**
|
||||
* 根据学院ID和角色Key查询具备该角色的用户列表
|
||||
|
||||
+4
-4
@@ -171,7 +171,7 @@ public class XgClassTeacherCounselorRelServiceImpl implements IXgClassTeacherCou
|
||||
|
||||
// 3. 更新学生表xg_student_msg表中的班主任信息
|
||||
LambdaUpdateWrapper<XgStudentMsg> studentUpdateWrapper = Wrappers.lambdaUpdate(XgStudentMsg.class)
|
||||
.eq(XgStudentMsg::getClassId, bo.getClassId())
|
||||
.eq(XgStudentMsg::getClassId, String.valueOf(bo.getClassId()))
|
||||
.set(XgStudentMsg::getClassTeacherId, null)
|
||||
.set(XgStudentMsg::getClassTeacherName, null);
|
||||
int updateResult11 = xgStudentMsgMapper.update(null, studentUpdateWrapper);
|
||||
@@ -195,7 +195,7 @@ public class XgClassTeacherCounselorRelServiceImpl implements IXgClassTeacherCou
|
||||
|
||||
// 3. 更新学生表xg_student_msg表中的班主任信息
|
||||
LambdaUpdateWrapper<XgStudentMsg> studentUpdateWrapper = Wrappers.lambdaUpdate(XgStudentMsg.class)
|
||||
.eq(XgStudentMsg::getClassId, bo.getClassId())
|
||||
.eq(XgStudentMsg::getClassId, String.valueOf(bo.getClassId()))
|
||||
.set(XgStudentMsg::getClassTeacherId, bo.getTeacherId())
|
||||
.set(XgStudentMsg::getClassTeacherName, bo.getTeacherName());
|
||||
int updateResult11 = xgStudentMsgMapper.update(null, studentUpdateWrapper);
|
||||
@@ -273,7 +273,7 @@ public class XgClassTeacherCounselorRelServiceImpl implements IXgClassTeacherCou
|
||||
|
||||
// 3. 更新学生表xg_student_msg表中的辅导员信息
|
||||
LambdaUpdateWrapper<XgStudentMsg> studentUpdateWrapper = Wrappers.lambdaUpdate(XgStudentMsg.class)
|
||||
.eq(XgStudentMsg::getClassId, bo.getClassId())
|
||||
.eq(XgStudentMsg::getClassId, String.valueOf(bo.getClassId()))
|
||||
.set(XgStudentMsg::getCounselorId, null)
|
||||
.set(XgStudentMsg::getCounselorName, null);
|
||||
int updateResult11 = xgStudentMsgMapper.update(null, studentUpdateWrapper);
|
||||
@@ -295,7 +295,7 @@ public class XgClassTeacherCounselorRelServiceImpl implements IXgClassTeacherCou
|
||||
bo.getClassId(), bo.getTeacherId(), bo.getTeacherName());
|
||||
// 3. 更新学生表xg_student_msg表中的辅导员信息
|
||||
LambdaUpdateWrapper<XgStudentMsg> studentUpdateWrapper = Wrappers.lambdaUpdate(XgStudentMsg.class)
|
||||
.eq(XgStudentMsg::getClassId, bo.getClassId())
|
||||
.eq(XgStudentMsg::getClassId, String.valueOf(bo.getClassId()))
|
||||
.set(XgStudentMsg::getCounselorId, bo.getTeacherId())
|
||||
.set(XgStudentMsg::getCounselorName, bo.getTeacherName());
|
||||
int updateResult11 = xgStudentMsgMapper.update(null, studentUpdateWrapper);
|
||||
|
||||
+1
-1
@@ -1472,7 +1472,7 @@ public class XgDormBedStudentServiceImpl implements IXgDormBedStudentService {
|
||||
studentQuery.eq(XgStudentMsg::getStudentStatus, "1") // 学生状态为正常
|
||||
.eq(XgStudentMsg::getDeleted, 0L) // 未删除
|
||||
.eq(XgStudentMsg::getIsBoarder, "1") // 需要住校
|
||||
.eq(XgStudentMsg::getClassId, targetClassId) // 指定班级
|
||||
.eq(XgStudentMsg::getClassId, String.valueOf(targetClassId)) // 指定班级(转换为String类型)
|
||||
.orderByDesc(XgStudentMsg::getStudentNo); // 按学号倒序排序
|
||||
|
||||
List<XgStudentMsg> boardingStudents = xgStudentMsgMapper.selectList(studentQuery);
|
||||
|
||||
+3
-1
@@ -82,7 +82,8 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
@Override
|
||||
public TableDataInfo<XgDormRoomVo> queryPageList(XgDormRoomBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<XgDormRoom> lqw = buildQueryWrapper(bo);
|
||||
Page<XgDormRoomVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
// 由于buildQueryWrapper中已经设置了业务排序,禁用PageQuery的默认排序(创建时间倒序)
|
||||
Page<XgDormRoomVo> result = baseMapper.selectVoPage(pageQuery.disableDefaultOrder().build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
@@ -163,6 +164,7 @@ public class XgDormRoomServiceImpl implements IXgDormRoomService {
|
||||
private LambdaQueryWrapper<XgDormRoom> buildQueryWrapper(XgDormRoomBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<XgDormRoom> lqw = Wrappers.lambdaQuery();
|
||||
// 设置业务排序规则
|
||||
lqw.orderByAsc(XgDormRoom::getFloorNum); // 第一优先级:按楼层升序
|
||||
lqw.orderByAsc(XgDormRoom::getSort); // 第二优先级:按排序号升序
|
||||
lqw.orderByAsc(XgDormRoom::getRoomName); // 第三优先级:按房间名称升序
|
||||
|
||||
+20
-2
@@ -1098,7 +1098,16 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService {
|
||||
log.info("根据学生ID获取学院请假审批人列表 - 学生ID: {}", studentId);
|
||||
|
||||
// 1. 根据学生ID查询学院ID
|
||||
Long collegeId = baseMapper.selectCollegeIdByStudentId(studentId);
|
||||
String collegeIdStr = baseMapper.selectCollegeIdByStudentId(studentId);
|
||||
Long collegeId = null;
|
||||
if (StringUtils.isNotBlank(collegeIdStr)) {
|
||||
try {
|
||||
collegeId = Long.valueOf(collegeIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("学院ID格式错误,无法转换为Long类型 - 学生ID: {}, collegeIdStr: {}", studentId, collegeIdStr);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (collegeId == null) {
|
||||
log.warn("未找到学生对应的学院信息 - 学生ID: {}", studentId);
|
||||
return new ArrayList<>();
|
||||
@@ -1124,7 +1133,16 @@ public class XgStudentMsgServiceImpl implements IXgStudentMsgService {
|
||||
log.info("根据学生ID获取二级学院分管领导ID列表 - 学生ID: {}", studentId);
|
||||
|
||||
// 1. 根据学生ID查询学院ID
|
||||
Long collegeId = baseMapper.selectCollegeIdByStudentId(studentId);
|
||||
String collegeIdStr = baseMapper.selectCollegeIdByStudentId(studentId);
|
||||
Long collegeId = null;
|
||||
if (StringUtils.isNotBlank(collegeIdStr)) {
|
||||
try {
|
||||
collegeId = Long.valueOf(collegeIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("学院ID格式错误,无法转换为Long类型 - 学生ID: {}, collegeIdStr: {}", studentId, collegeIdStr);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
if (collegeId == null) {
|
||||
log.warn("未找到学生对应的学院信息 - 学生ID: {}", studentId);
|
||||
return new ArrayList<>();
|
||||
|
||||
+1
-1
@@ -148,7 +148,7 @@ public class XgStudentServiceImpl implements IXgStudentService {
|
||||
// "#result == null || #result.isEmpty()")
|
||||
public List<XgStudentVo> getStudentsByClassId(Long classId) {
|
||||
LambdaQueryWrapper<XgStudentMsg> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(XgStudentMsg::getClassId, classId);
|
||||
lqw.eq(XgStudentMsg::getClassId, String.valueOf(classId));
|
||||
lqw.eq(XgStudentMsg::getStudentStatus, "1"); // 只查询在籍学生
|
||||
lqw.orderByDesc(XgStudentMsg::getStudentNo); // 按学号倒序排序
|
||||
return baseMapper.selectVoList(lqw);
|
||||
|
||||
+1
-1
@@ -148,7 +148,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</select>
|
||||
|
||||
<!-- 根据学生ID查询学院ID -->
|
||||
<select id="selectCollegeIdByStudentId" resultType="java.lang.Long">
|
||||
<select id="selectCollegeIdByStudentId" resultType="java.lang.String">
|
||||
SELECT college_id
|
||||
FROM xg_student_msg
|
||||
WHERE id = #{studentId}
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
- **[学生换班级记录表.sql](学生换班级记录表.sql)** - 学生换班级记录表的完整建表SQL脚本
|
||||
- **[学生换班级记录表设计说明.md](学生换班级记录表设计说明.md)** - 详细的表结构设计说明文档
|
||||
|
||||
### 🔧 处理脚本(新增)
|
||||
- **[process_student_class_change.sh](process_student_class_change.sh)** - 准实时处理换班级工单的主脚本
|
||||
- **[control_scripts.sh](control_scripts.sh)** - 脚本控制程序,支持启动、停止、重启等操作
|
||||
- **[health_check.sh](health_check.sh)** - 服务健康检查和监控脚本
|
||||
- **[data.conf](data.conf)** - 数据库连接和脚本运行配置
|
||||
- **[README_换班级脚本.md](README_换班级脚本.md)** - 换班级处理脚本的详细技术文档
|
||||
|
||||
## 🎯 业务概述
|
||||
|
||||
学生换班级记录表用于记录学校所有学生换班级的操作历史,包括:
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
# 学生换班级处理脚本
|
||||
|
||||
## 📁 概述
|
||||
|
||||
本脚本用于准实时处理学生换班级工单,实现学生信息的自动更新和干部信息的终止处理。参考退学、休学、复学、毕业脚本的架构设计,提供完整的换班级业务处理能力。
|
||||
|
||||
## 🎯 业务需求
|
||||
|
||||
### 1. 干部信息终止
|
||||
- 参考退学等脚本思路,终止学生的干部职务
|
||||
- 设置干部状态为"换班级终止"(cadre_status = '5')
|
||||
- 记录终止原因和时间
|
||||
|
||||
### 2. 学生信息更新
|
||||
- 更新学生基本班级信息(学院、专业、班级、年级等)
|
||||
- 更新预留字段,从新班级表获取完整信息
|
||||
- 特别处理 `academic_level` 字段,对应 `xg_class_msg.class_type`
|
||||
|
||||
## 📋 文件清单
|
||||
|
||||
### 🔧 核心脚本
|
||||
- **[process_student_class_change.sh](process_student_class_change.sh)** - 主处理脚本,实现换班级业务逻辑
|
||||
- **[control_scripts.sh](control_scripts.sh)** - 脚本控制程序,支持启动、停止、重启等操作
|
||||
- **[health_check.sh](health_check.sh)** - 服务健康检查脚本
|
||||
|
||||
### ⚙️ 配置文件
|
||||
- **[data.conf](data.conf)** - 数据库连接配置
|
||||
|
||||
### 📊 数据库设计
|
||||
- **[学生换班级记录表.sql](学生换班级记录表.sql)** - 换班级记录表结构
|
||||
- **[学生换班级记录表设计说明.md](学生换班级记录表设计说明.md)** - 详细设计文档
|
||||
|
||||
## 🔄 处理流程
|
||||
|
||||
```
|
||||
换班级工单提交 → 脚本检测 → 获取新班级信息 → 终止干部职务 → 更新学生信息 → 标记处理完成
|
||||
```
|
||||
|
||||
### 详细步骤
|
||||
|
||||
1. **工单检测**: 扫描 `status = '0'` 的换班级记录
|
||||
2. **班级信息获取**: 从 `xg_class_msg` 表获取新班级完整信息
|
||||
3. **干部信息终止**:
|
||||
- 设置 `is_current = 0`
|
||||
- 设置 `cadre_status = '5'`(换班级终止)
|
||||
- 记录终止日期和原因
|
||||
4. **学生信息更新**:
|
||||
- 更新基础班级信息(college_id, major_id, class_id等)
|
||||
- 更新预留字段(school_system, academic_level, training_type等)
|
||||
- academic_level 对应 class_type
|
||||
5. **工单状态更新**: 设置 `status = '1'` 标记处理完成
|
||||
|
||||
## 🗄️ 数据映射
|
||||
|
||||
### 新班级信息获取
|
||||
```sql
|
||||
SELECT
|
||||
college_id, college_name, major_id, major_name,
|
||||
class_code, class_name, class_type, grade,
|
||||
training_type, counselor_id, counselor_name,
|
||||
class_teacher_id, class_teacher_name, school_system
|
||||
FROM xg_class_msg
|
||||
WHERE id = {new_class_id}
|
||||
```
|
||||
|
||||
### 学生信息更新字段
|
||||
```sql
|
||||
UPDATE xg_student_msg SET
|
||||
-- 基础班级信息
|
||||
college_id = '{college_id}',
|
||||
college_name = '{college_name}',
|
||||
major_id = '{major_id}',
|
||||
major_name = '{major_name}',
|
||||
class_id = '{new_class_id}',
|
||||
class_name = '{class_name}',
|
||||
grade = '{grade}',
|
||||
|
||||
-- 预留字段 (7182-7195行)
|
||||
school_system = '{school_system}',
|
||||
academic_level = '{class_type}', -- 关键映射
|
||||
training_type = '{training_type}',
|
||||
counselor_id = {counselor_id},
|
||||
counselor_name = '{counselor_name}',
|
||||
class_teacher_id = {class_teacher_id},
|
||||
class_teacher_name = '{class_teacher_name}',
|
||||
|
||||
-- 更新信息
|
||||
update_by = {operator_id},
|
||||
update_time = NOW()
|
||||
WHERE id = {student_id}
|
||||
```
|
||||
|
||||
## 🚀 部署使用
|
||||
|
||||
### 1. 配置数据库连接
|
||||
```bash
|
||||
vim data.conf
|
||||
# 修改数据库连接信息
|
||||
```
|
||||
|
||||
### 2. 启动服务
|
||||
```bash
|
||||
# 启动换班级处理服务
|
||||
./control_scripts.sh start class_change
|
||||
|
||||
# 或启动所有服务
|
||||
./control_scripts.sh startall
|
||||
```
|
||||
|
||||
### 3. 查看服务状态
|
||||
```bash
|
||||
# 查看所有服务状态
|
||||
./control_scripts.sh statusall
|
||||
|
||||
# 查看特定服务
|
||||
./control_scripts.sh status class_change
|
||||
```
|
||||
|
||||
### 4. 健康检查
|
||||
```bash
|
||||
# 执行健康检查
|
||||
./health_check.sh
|
||||
|
||||
# 生成详细报告
|
||||
./health_check.sh --report
|
||||
```
|
||||
|
||||
### 5. 停止服务
|
||||
```bash
|
||||
# 停止换班级处理服务
|
||||
./control_scripts.sh stop class_change
|
||||
|
||||
# 或停止所有服务
|
||||
./control_scripts.sh stopall
|
||||
```
|
||||
|
||||
## 📊 监控日志
|
||||
|
||||
### 日志位置
|
||||
- **主日志**: `./student_class_change/process_student_class_change_*.log`
|
||||
- **包含信息**: 处理详情、错误信息、性能统计
|
||||
|
||||
### 日志内容示例
|
||||
```
|
||||
[2025-01-25 10:00:00] [INFO] Starting student class change processing daemon
|
||||
[2025-01-25 10:00:00] [INFO] Processing student change - ID: 123, Student: 20240001 (456), New Class ID: 789
|
||||
[2025-01-25 10:00:00] [INFO] Successfully processed student class change - ID: 123, Student: 20240001
|
||||
```
|
||||
|
||||
## ⚙️ 配置参数
|
||||
|
||||
### data.conf 配置项
|
||||
```bash
|
||||
# 数据库配置
|
||||
DB_HOST="localhost"
|
||||
DB_PORT="3306"
|
||||
DB_NAME="hzdyjs_xg"
|
||||
DB_USER="root"
|
||||
DB_PASS="password"
|
||||
|
||||
# 脚本配置
|
||||
LOG_DIR="./student_class_change"
|
||||
BATCH_SIZE=100 # 每批处理数量
|
||||
MAX_RETRY=3 # 最大重试次数
|
||||
RETRY_DELAY=5 # 重试间隔(秒)
|
||||
CYCLE_INTERVAL=600 # 检查周期(秒)
|
||||
```
|
||||
|
||||
## 🔧 故障排除
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **数据库连接失败**
|
||||
```bash
|
||||
# 检查配置
|
||||
cat data.conf
|
||||
# 测试连接
|
||||
mysql -h$DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASS $DB_NAME -e "SELECT 1;"
|
||||
```
|
||||
|
||||
2. **服务无法启动**
|
||||
```bash
|
||||
# 检查脚本权限
|
||||
ls -la *.sh
|
||||
# 设置执行权限
|
||||
chmod +x *.sh
|
||||
```
|
||||
|
||||
3. **处理失败**
|
||||
```bash
|
||||
# 查看日志
|
||||
tail -f ./student_class_change/*.log
|
||||
# 检查数据
|
||||
mysql -e "SELECT * FROM xg_student_class_change WHERE status = '0';"
|
||||
```
|
||||
|
||||
### 性能优化
|
||||
|
||||
1. **索引检查**: 确保相关表的索引完整
|
||||
2. **批量处理**: 每次处理适当数量的记录
|
||||
3. **日志轮转**: 定期清理旧日志文件
|
||||
4. **监控资源**: 监控CPU、内存、磁盘使用情况
|
||||
|
||||
## 📈 统计监控
|
||||
|
||||
### 处理统计
|
||||
```sql
|
||||
-- 查看处理统计
|
||||
SELECT
|
||||
COUNT(*) as total_records,
|
||||
SUM(CASE WHEN status = '0' THEN 1 ELSE 0 END) as pending,
|
||||
SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) as processed
|
||||
FROM xg_student_class_change
|
||||
WHERE deleted = 0;
|
||||
|
||||
-- 查看最近处理情况
|
||||
SELECT
|
||||
DATE(update_time) as process_date,
|
||||
COUNT(*) as processed_count
|
||||
FROM xg_student_class_change
|
||||
WHERE status = '1'
|
||||
AND update_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
|
||||
GROUP BY DATE(update_time)
|
||||
ORDER BY process_date DESC;
|
||||
```
|
||||
|
||||
## 🔄 扩展开发
|
||||
|
||||
### 添加新的业务逻辑
|
||||
1. 在 `process_student_class_change()` 函数中添加处理步骤
|
||||
2. 更新事务SQL,确保数据一致性
|
||||
3. 添加相应的日志记录
|
||||
4. 更新健康检查逻辑
|
||||
|
||||
### 自定义配置
|
||||
1. 在 `data.conf` 中添加新配置项
|
||||
2. 在脚本中读取和使用配置
|
||||
3. 更新文档说明
|
||||
|
||||
## 📞 技术支持
|
||||
|
||||
如有疑问或需要技术支持,请联系项目技术团队。
|
||||
|
||||
---
|
||||
|
||||
**创建时间**: 2025-01-25
|
||||
**维护人员**: AI Assistant
|
||||
**版本**: v1.0.0
|
||||
Executable
+332
@@ -0,0 +1,332 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生换班级处理脚本控制程序
|
||||
# 用于启动、停止、重启处理脚本
|
||||
# ===========================================
|
||||
|
||||
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 "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
# Script definitions
|
||||
declare -A SCRIPTS=(
|
||||
["class_change"]="process_student_class_change.sh"
|
||||
)
|
||||
|
||||
# PID files
|
||||
PID_DIR="${SCRIPT_DIR}/pids"
|
||||
mkdir -p "$PID_DIR"
|
||||
|
||||
# Functions
|
||||
log() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo "[$timestamp] [$level] $message"
|
||||
}
|
||||
|
||||
get_pid_file() {
|
||||
local script_name="$1"
|
||||
echo "${PID_DIR}/${script_name}.pid"
|
||||
}
|
||||
|
||||
get_lock_file() {
|
||||
local script_name="$1"
|
||||
echo "${SCRIPT_DIR}/${script_name}.lock"
|
||||
}
|
||||
|
||||
is_running() {
|
||||
local script_name="$1"
|
||||
local pid_file=$(get_pid_file "$script_name")
|
||||
local lock_file=$(get_lock_file "$script_name")
|
||||
|
||||
# Check PID file
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
local pid=$(cat "$pid_file")
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
return 0 # Running
|
||||
else
|
||||
log "WARN" "删除脚本 $script_name 的过期PID文件"
|
||||
rm -f "$pid_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check lock file
|
||||
if [[ -f "$lock_file" ]]; then
|
||||
local lock_pid=$(cat "$lock_file")
|
||||
if kill -0 "$lock_pid" 2>/dev/null; then
|
||||
return 0 # Running
|
||||
else
|
||||
log "WARN" "删除脚本 $script_name 的过期锁定文件"
|
||||
rm -f "$lock_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1 # Not running
|
||||
}
|
||||
|
||||
start_script() {
|
||||
local script_name="$1"
|
||||
local script_file="${SCRIPT_DIR}/${SCRIPTS[$script_name]}"
|
||||
local pid_file=$(get_pid_file "$script_name")
|
||||
|
||||
if [[ ! -f "$script_file" ]]; then
|
||||
log "ERROR" "脚本文件未找到: $script_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if is_running "$script_name"; then
|
||||
log "INFO" "$script_name 已在运行"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "INFO" "正在启动 $script_name..."
|
||||
chmod +x "$script_file"
|
||||
|
||||
# Start script in background
|
||||
nohup "$script_file" > /dev/null 2>&1 &
|
||||
local pid=$!
|
||||
|
||||
# Save PID
|
||||
echo $pid > "$pid_file"
|
||||
|
||||
# Wait a moment and check if it's still running
|
||||
sleep 2
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
log "INFO" "$script_name 启动成功 (PID: $pid)"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "$script_name 启动失败"
|
||||
rm -f "$pid_file"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop_script() {
|
||||
local script_name="$1"
|
||||
local pid_file=$(get_pid_file "$script_name")
|
||||
local lock_file=$(get_lock_file "$script_name")
|
||||
|
||||
if ! is_running "$script_name"; then
|
||||
log "INFO" "$script_name 未运行"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "INFO" "正在停止 $script_name..."
|
||||
|
||||
# Try graceful shutdown first
|
||||
local pids=()
|
||||
[[ -f "$pid_file" ]] && pids+=($(cat "$pid_file"))
|
||||
[[ -f "$lock_file" ]] && pids+=($(cat "$lock_file"))
|
||||
|
||||
for pid in "${pids[@]}"; do
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Wait for graceful shutdown
|
||||
local count=0
|
||||
while [[ $count -lt 10 ]] && is_running "$script_name"; do
|
||||
sleep 1
|
||||
((count++))
|
||||
done
|
||||
|
||||
# Force kill if still running
|
||||
if is_running "$script_name"; then
|
||||
log "WARN" "Graceful shutdown failed, force killing $script_name..."
|
||||
for pid in "${pids[@]}"; do
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Clean up files
|
||||
rm -f "$pid_file" "$lock_file"
|
||||
|
||||
if is_running "$script_name"; then
|
||||
log "ERROR" "Failed to stop $script_name"
|
||||
return 1
|
||||
else
|
||||
log "INFO" "$script_name stopped successfully"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
restart_script() {
|
||||
local script_name="$1"
|
||||
|
||||
log "INFO" "正在重启 $script_name..."
|
||||
if stop_script "$script_name" && start_script "$script_name"; then
|
||||
log "INFO" "$script_name 重启成功"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "$script_name 重启失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
status_script() {
|
||||
local script_name="$1"
|
||||
|
||||
if is_running "$script_name"; then
|
||||
local pid_file=$(get_pid_file "$script_name")
|
||||
local lock_file=$(get_lock_file "$script_name")
|
||||
local pid=""
|
||||
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
pid=$(cat "$pid_file")
|
||||
elif [[ -f "$lock_file" ]]; then
|
||||
pid=$(cat "$lock_file")
|
||||
fi
|
||||
|
||||
echo "$script_name 正在运行 (PID: $pid)"
|
||||
return 0
|
||||
else
|
||||
echo "$script_name 未运行"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "用法: $0 {start|stop|restart|status} {script_name}"
|
||||
echo " $0 {startall|stopall|restartall|statusall}"
|
||||
echo ""
|
||||
echo "可用脚本:"
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
echo " $script - ${SCRIPTS[$script]}"
|
||||
done
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 start class_change # 启动换班级处理"
|
||||
echo " $0 stop class_change # 停止换班级处理"
|
||||
echo " $0 restart class_change # 重启换班级处理"
|
||||
echo " $0 status class_change # 检查换班级处理状态"
|
||||
echo " $0 startall # 启动所有脚本"
|
||||
echo " $0 stopall # 停止所有脚本"
|
||||
echo " $0 statusall # 检查所有脚本状态"
|
||||
}
|
||||
|
||||
# Main logic
|
||||
case "${1:-}" in
|
||||
start)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${SCRIPTS[$2]:-}" ]]; then
|
||||
start_script "$2"
|
||||
else
|
||||
echo "未知脚本: $2"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${SCRIPTS[$2]:-}" ]]; then
|
||||
stop_script "$2"
|
||||
else
|
||||
echo "未知脚本: $2"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${SCRIPTS[$2]:-}" ]]; then
|
||||
restart_script "$2"
|
||||
else
|
||||
echo "未知脚本: $2"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
status)
|
||||
if [[ -z "${2:-}" ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${SCRIPTS[$2]:-}" ]]; then
|
||||
status_script "$2"
|
||||
else
|
||||
echo "未知脚本: $2"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
startall)
|
||||
log "INFO" "正在启动所有脚本..."
|
||||
local failed=()
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
if ! start_script "$script"; then
|
||||
failed+=("$script")
|
||||
fi
|
||||
done
|
||||
if [[ ${#failed[@]} -eq 0 ]]; then
|
||||
log "INFO" "所有脚本启动成功"
|
||||
else
|
||||
log "ERROR" "启动脚本失败: ${failed[*]}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
stopall)
|
||||
log "INFO" "正在停止所有脚本..."
|
||||
local failed=()
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
if ! stop_script "$script"; then
|
||||
failed+=("$script")
|
||||
fi
|
||||
done
|
||||
if [[ ${#failed[@]} -eq 0 ]]; then
|
||||
log "INFO" "所有脚本停止成功"
|
||||
else
|
||||
log "ERROR" "停止脚本失败: ${failed[*]}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
restartall)
|
||||
log "INFO" "正在重启所有脚本..."
|
||||
local failed=()
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
if ! restart_script "$script"; then
|
||||
failed+=("$script")
|
||||
fi
|
||||
done
|
||||
if [[ ${#failed[@]} -eq 0 ]]; then
|
||||
log "INFO" "所有脚本重启成功"
|
||||
else
|
||||
log "ERROR" "重启脚本失败: ${failed[*]}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
statusall)
|
||||
log "INFO" "正在检查所有脚本的状态..."
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
echo -n "$script: "
|
||||
status_script "$script"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,17 @@
|
||||
# Database configuration
|
||||
DB_HOST="47.99.164.66"
|
||||
DB_PORT="3306"
|
||||
DB_NAME="hzdyjs_xg"
|
||||
DB_USER="root"
|
||||
DB_PASS="hn02le.34lkdLKD"
|
||||
|
||||
# Script configuration
|
||||
LOG_DIR="${SCRIPT_DIR}/student_class_change"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOCK_FILE="${SCRIPT_DIR}/script.lock"
|
||||
|
||||
# Processing configuration
|
||||
BATCH_SIZE=100
|
||||
MAX_RETRY=3
|
||||
RETRY_DELAY=5
|
||||
CYCLE_INTERVAL=600 # 循环间隔时间(秒),默认10分钟
|
||||
Executable
+348
@@ -0,0 +1,348 @@
|
||||
#!/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_pending_records() {
|
||||
info "正在检查待处理的换班级记录..."
|
||||
|
||||
local pending_count
|
||||
if pending_count=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "
|
||||
SELECT COUNT(*) as pending
|
||||
FROM xg_student_class_change
|
||||
WHERE status = '0' AND deleted = 0;
|
||||
" 2>/dev/null | tail -n1); then
|
||||
|
||||
if [[ "$pending_count" -eq 0 ]]; then
|
||||
success "无待处理的换班级记录"
|
||||
elif [[ "$pending_count" -lt 10 ]]; then
|
||||
warning "$pending_count 条待处理的换班级记录"
|
||||
else
|
||||
error "$pending_count 条待处理的换班级记录 (积压严重)"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
error "检查待处理记录失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查最近的处理活动
|
||||
check_recent_processing() {
|
||||
info "正在检查最近的处理活动..."
|
||||
|
||||
local recent_count
|
||||
if recent_count=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "
|
||||
SELECT COUNT(*) as recent
|
||||
FROM xg_student_class_change
|
||||
WHERE status = '1'
|
||||
AND update_time >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
|
||||
AND deleted = 0;
|
||||
" 2>/dev/null | tail -n1); then
|
||||
|
||||
if [[ "$recent_count" -gt 0 ]]; then
|
||||
success "最近一小时处理了 $recent_count 条记录"
|
||||
else
|
||||
warning "最近一小时未处理任何记录"
|
||||
fi
|
||||
return 0
|
||||
else
|
||||
error "检查最近处理活动失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查日志文件
|
||||
check_logs() {
|
||||
info "正在检查日志文件..."
|
||||
|
||||
if [[ -d "$LOG_DIR" ]]; then
|
||||
local log_count
|
||||
log_count=$(find "$LOG_DIR" -name "*.log" -type f -mtime -1 2>/dev/null | wc -l)
|
||||
|
||||
if [[ "$log_count" -gt 0 ]]; then
|
||||
success "发现最近的日志文件 ($log_count 个文件来自最近24小时)"
|
||||
else
|
||||
warning "未发现最近的日志文件"
|
||||
fi
|
||||
|
||||
# 检查错误日志
|
||||
local error_count
|
||||
error_count=$(find "$LOG_DIR" -name "*.log" -type f -exec grep -l "ERROR" {} \; 2>/dev/null | wc -l)
|
||||
|
||||
if [[ "$error_count" -gt 0 ]]; then
|
||||
warning "$error_count 个日志文件包含错误"
|
||||
else
|
||||
success "最近日志中未发现错误消息"
|
||||
fi
|
||||
else
|
||||
error "日志目录未找到: $LOG_DIR"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查磁盘空间
|
||||
check_disk_space() {
|
||||
info "正在检查磁盘空间..."
|
||||
|
||||
local disk_usage
|
||||
disk_usage=$(df "$SCRIPT_DIR" | tail -1 | awk '{print $5}' | sed 's/%//')
|
||||
|
||||
if [[ "$disk_usage" -lt 80 ]]; then
|
||||
success "磁盘使用率: ${disk_usage}%"
|
||||
elif [[ "$disk_usage" -lt 90 ]]; then
|
||||
warning "磁盘使用率: ${disk_usage}% (接近限制)"
|
||||
else
|
||||
error "磁盘使用率: ${disk_usage}% (严重)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 检查内存使用情况
|
||||
check_memory() {
|
||||
info "正在检查内存使用情况..."
|
||||
|
||||
local mem_usage
|
||||
mem_usage=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}')
|
||||
|
||||
if [[ "$mem_usage" -lt 80 ]]; then
|
||||
success "内存使用率: ${mem_usage}%"
|
||||
elif [[ "$mem_usage" -lt 90 ]]; then
|
||||
warning "内存使用率: ${mem_usage}% (接近限制)"
|
||||
else
|
||||
error "内存使用率: ${mem_usage}% (严重)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate health report
|
||||
generate_report() {
|
||||
local report_file="${SCRIPT_DIR}/health_report_$(date +%Y%m%d_%H%M%S).txt"
|
||||
|
||||
{
|
||||
echo "=== 学生换班级处理服务健康检查报告 ==="
|
||||
echo "检查时间: $(date)"
|
||||
echo "服务器信息: $(hostname)"
|
||||
echo ""
|
||||
|
||||
echo "=== 数据库连接 ==="
|
||||
if check_database; then
|
||||
echo "✓ 数据库连接正常"
|
||||
else
|
||||
echo "✗ 数据库连接异常"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "=== 服务状态 ==="
|
||||
if check_service "class_change" "学生换班级处理服务"; then
|
||||
echo "✓ 学生换班级处理服务运行正常"
|
||||
else
|
||||
echo "✗ 学生换班级处理服务未运行"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "=== 业务数据检查 ==="
|
||||
check_pending_records
|
||||
echo ""
|
||||
check_recent_processing
|
||||
echo ""
|
||||
|
||||
echo "=== 系统资源 ==="
|
||||
check_disk_space
|
||||
echo ""
|
||||
check_memory
|
||||
echo ""
|
||||
|
||||
echo "=== 日志检查 ==="
|
||||
check_logs
|
||||
echo ""
|
||||
|
||||
echo "报告生成完成"
|
||||
} > "$report_file" 2>/dev/null
|
||||
|
||||
success "健康检查报告已生成: $report_file"
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
echo ""
|
||||
echo "=== 学生换班级处理服务健康检查 ==="
|
||||
echo "检查时间: $(date)"
|
||||
echo "服务器信息: $(hostname)"
|
||||
echo ""
|
||||
|
||||
local checks_passed=0
|
||||
local total_checks=0
|
||||
|
||||
# Database connection
|
||||
echo "=== 数据库连接 ==="
|
||||
((total_checks++))
|
||||
check_database && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
# Service status
|
||||
echo "=== 服务状态 ==="
|
||||
((total_checks++))
|
||||
check_service "class_change" "学生换班级处理服务" && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
# Business data
|
||||
echo "=== 业务数据检查 ==="
|
||||
((total_checks++))
|
||||
check_pending_records && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
((total_checks++))
|
||||
check_recent_processing && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
# System resources
|
||||
echo "=== 系统资源 ==="
|
||||
((total_checks++))
|
||||
check_disk_space && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
((total_checks++))
|
||||
check_memory && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
# Logs
|
||||
echo "=== 日志检查 ==="
|
||||
((total_checks++))
|
||||
check_logs && ((checks_passed++))
|
||||
echo ""
|
||||
|
||||
# 总结
|
||||
echo "=== 检查总结 ==="
|
||||
local success_rate=$((checks_passed * 100 / total_checks))
|
||||
echo "通过检查: $checks_passed/$total_checks ($success_rate%)"
|
||||
|
||||
if [[ $success_rate -eq 100 ]]; then
|
||||
success "所有检查通过,服务运行正常"
|
||||
exit 0
|
||||
elif [[ $success_rate -ge 80 ]]; then
|
||||
warning "大部分检查通过,服务运行基本正常"
|
||||
exit 0
|
||||
else
|
||||
error "多项检查失败,建议立即检查服务状态"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 命令行选项
|
||||
case "${1:-}" in
|
||||
--report)
|
||||
generate_report
|
||||
;;
|
||||
--help|-h)
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "选项:"
|
||||
echo " --report 生成详细的健康检查报告"
|
||||
echo " --help 显示此帮助信息"
|
||||
echo ""
|
||||
echo "无选项时,执行标准健康检查。"
|
||||
;;
|
||||
*)
|
||||
main "$@"
|
||||
;;
|
||||
esac
|
||||
Executable
+301
@@ -0,0 +1,301 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生换班级处理脚本
|
||||
# 处理类型: CLASS_CHANGE(换班级)
|
||||
# ===========================================
|
||||
|
||||
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 "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
# Create log directory
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
# Log file
|
||||
LOG_FILE="${LOG_DIR}/process_student_class_change_$(date +%Y%m%d_%H%M%S).log"
|
||||
|
||||
# Lock file to prevent multiple instances
|
||||
LOCK_FILE="${SCRIPT_DIR}/process_student_class_change.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
|
||||
}
|
||||
|
||||
# 检查脚本是否已在运行
|
||||
if [[ -f "$LOCK_FILE" ]]; then
|
||||
if kill -0 $(cat "$LOCK_FILE") 2>/dev/null; then
|
||||
log "INFO" "脚本已在运行 (PID: $(cat "$LOCK_FILE"))"
|
||||
exit 1
|
||||
else
|
||||
log "WARN" "删除过期的锁定文件"
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create lock file
|
||||
echo $$ > "$LOCK_FILE"
|
||||
|
||||
# 清理函数
|
||||
cleanup() {
|
||||
[[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE"
|
||||
log "INFO" "脚本执行完成"
|
||||
}
|
||||
|
||||
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执行失败: $sql"
|
||||
log "ERROR" "MySQL错误: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
# Process student class change
|
||||
process_student_class_change() {
|
||||
local record_id="$1"
|
||||
local student_id="$2"
|
||||
local student_no="$3"
|
||||
local new_class_id="$4"
|
||||
local operator_id="${5:-1}"
|
||||
|
||||
log "INFO" "Processing student class change - ID: $record_id, Student: $student_no ($student_id), New Class ID: $new_class_id"
|
||||
|
||||
# Get new class information
|
||||
local class_info_sql="
|
||||
SELECT
|
||||
c.college_id, c.college_name, c.major_id, c.major_name,
|
||||
c.class_code, c.class_name, c.class_type, c.grade,
|
||||
c.training_type, c.counselor_id, c.counselor_name,
|
||||
c.class_teacher_id, c.class_teacher_name, c.school_system
|
||||
FROM xg_class_msg c
|
||||
WHERE c.id = $new_class_id AND c.deleted = 0
|
||||
"
|
||||
|
||||
local class_info
|
||||
class_info=$(execute_sql "$class_info_sql")
|
||||
|
||||
if [[ -z "$class_info" || "$class_info" == *"Empty set"* ]]; then
|
||||
log "ERROR" "获取班级ID为 $new_class_id 的班级信息失败"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Parse class information (skip header and separator lines, get data row)
|
||||
local class_data
|
||||
class_data=$(echo "$class_info" | grep -E '^[0-9]' | head -1)
|
||||
|
||||
if [[ -z "$class_data" ]]; then
|
||||
log "ERROR" "解析班级信息失败,无法获取数据行"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Use cut to extract specific fields reliably
|
||||
local college_id=$(echo "$class_data" | cut -f1)
|
||||
local college_name=$(echo "$class_data" | cut -f2)
|
||||
local major_id=$(echo "$class_data" | cut -f3)
|
||||
local major_name=$(echo "$class_data" | cut -f4)
|
||||
local class_code=$(echo "$class_data" | cut -f5)
|
||||
local class_name=$(echo "$class_data" | cut -f6)
|
||||
local class_type=$(echo "$class_data" | cut -f7)
|
||||
local grade=$(echo "$class_data" | cut -f8)
|
||||
local training_type=$(echo "$class_data" | cut -f9)
|
||||
local counselor_id=$(echo "$class_data" | cut -f10)
|
||||
local counselor_name=$(echo "$class_data" | cut -f11)
|
||||
local class_teacher_id=$(echo "$class_data" | cut -f12)
|
||||
local class_teacher_name=$(echo "$class_data" | cut -f13)
|
||||
local school_system=$(echo "$class_data" | cut -f14)
|
||||
|
||||
# Handle NULL values for IDs
|
||||
local counselor_id_value class_teacher_id_value
|
||||
if [[ "$counselor_id" == "NULL" || -z "$counselor_id" ]]; then
|
||||
counselor_id_value="NULL"
|
||||
else
|
||||
counselor_id_value="'$counselor_id'"
|
||||
fi
|
||||
|
||||
if [[ "$class_teacher_id" == "NULL" || -z "$class_teacher_id" ]]; then
|
||||
class_teacher_id_value="NULL"
|
||||
else
|
||||
class_teacher_id_value="'$class_teacher_id'"
|
||||
fi
|
||||
|
||||
# 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 xg_class_pos_msg_his SELECT * FROM xg_class_pos_msg WHERE student_id = $student_id;
|
||||
|
||||
-- 2. Terminate cadre positions (干部信息终止)
|
||||
UPDATE xg_class_pos_msg SET
|
||||
is_current = 0,
|
||||
cadre_status = '4', -- 免职
|
||||
dismissal_date = CURDATE(),
|
||||
dismissal_reason = '学生换班级',
|
||||
term_end_date = CURDATE(),
|
||||
term_duration = TIMESTAMPDIFF(MONTH, term_start_date, CURDATE()),
|
||||
update_by = $operator_id,
|
||||
update_time = NOW()
|
||||
WHERE student_id = $student_id AND is_current = 1;
|
||||
|
||||
-- 3. Update student information with new class data
|
||||
UPDATE xg_student_msg SET
|
||||
-- 基础班级信息
|
||||
college_id = '$college_id',
|
||||
college_name = '$college_name',
|
||||
major_id = '$major_id',
|
||||
major_name = '$major_name',
|
||||
class_id = '$new_class_id',
|
||||
class_name = '$class_name',
|
||||
grade = '$grade',
|
||||
|
||||
-- 预留字段从班级表关联获取的数据 (7182-7195行)
|
||||
school_system = '$school_system',
|
||||
academic_level = '$class_type', -- class_type 对应 academic_level
|
||||
training_type = '$training_type',
|
||||
counselor_id = $counselor_id_value,
|
||||
counselor_name = '$counselor_name',
|
||||
class_teacher_id = $class_teacher_id_value,
|
||||
class_teacher_name = '$class_teacher_name',
|
||||
|
||||
-- 更新信息
|
||||
update_by = $operator_id,
|
||||
update_time = NOW()
|
||||
WHERE id = $student_id;
|
||||
|
||||
-- 4. Update class change record status
|
||||
UPDATE xg_student_class_change SET
|
||||
status = '1', -- 已处理
|
||||
update_by = $operator_id,
|
||||
update_time = NOW()
|
||||
WHERE id = $record_id;
|
||||
|
||||
COMMIT;
|
||||
"
|
||||
|
||||
# 执行事务
|
||||
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" "处理类型: CLASS_CHANGE(换班级)"
|
||||
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, new_class_id, update_by
|
||||
FROM xg_student_class_change
|
||||
WHERE status = '0'
|
||||
AND deleted = 0
|
||||
AND effective_time <= NOW()
|
||||
ORDER BY create_time ASC
|
||||
LIMIT $BATCH_SIZE;
|
||||
"
|
||||
|
||||
local records
|
||||
records=$(execute_sql "$query_sql")
|
||||
|
||||
# 检查是否有记录需要处理
|
||||
# 过滤掉MySQL的边框和表头,只保留数据行
|
||||
local data_records
|
||||
data_records=$(echo "$records" | grep -E '^[0-9]' || true)
|
||||
|
||||
if [[ -z "$data_records" ]]; then
|
||||
log "INFO" "未找到未处理的记录,正在等待..."
|
||||
else
|
||||
log "INFO" "找到待处理记录,开始处理..."
|
||||
records="$data_records"
|
||||
|
||||
local processed_count=0
|
||||
local failed_count=0
|
||||
|
||||
# Process each record
|
||||
while IFS=$'\t' read -r record_id student_id student_no new_class_id 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_class_change "$record_id" "$student_id" "$student_no" "$new_class_id" "$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 <<< "$records"
|
||||
|
||||
log "INFO" "处理周期完成 - 已处理: $processed_count, 失败: $failed_count"
|
||||
fi
|
||||
|
||||
# 等待配置的间隔时间后开始下一个周期
|
||||
log "INFO" "等待 $CYCLE_INTERVAL 秒后开始下一个处理周期..."
|
||||
sleep $CYCLE_INTERVAL
|
||||
done
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
+19
-23
@@ -9,13 +9,10 @@
|
||||
1. **`process_student_changes.sh`** - 处理毕业、退学、休学的状态变更
|
||||
2. **`process_student_resume.sh`** - 处理复学的状态变更
|
||||
3. **`control_scripts.sh`** - 脚本控制程序(启动、停止、重启)
|
||||
4. **`start_services.sh`** - 一键启动所有服务
|
||||
5. **`stop_services.sh`** - 一键停止所有服务
|
||||
6. **`health_check.sh`** - 服务健康检查脚本
|
||||
7. **`data.conf`** - 数据库配置文件
|
||||
8. **`test_data.sql`** - 测试数据脚本
|
||||
9. **`optional_crontab_config.txt`** - 可选的定时任务配置(备用)
|
||||
10. **`demo.sh`** - 脚本使用演示
|
||||
4. **`health_check.sh`** - 服务健康检查脚本
|
||||
5. **`data.conf`** - 数据库配置文件
|
||||
6. **`test_data.sql`** - 测试数据脚本
|
||||
7. **`optional_crontab_config.txt`** - 可选的定时任务配置(备用)
|
||||
|
||||
### 处理逻辑
|
||||
|
||||
@@ -53,7 +50,7 @@ DB_USER="root" # 数据库用户名
|
||||
DB_PASS="password" # 数据库密码
|
||||
|
||||
# Script configuration
|
||||
LOG_DIR="/var/log/student_status_change" # 日志目录
|
||||
LOG_DIR="./student_status_change" # 日志目录
|
||||
SCRIPT_DIR="/path/to/scripts" # 脚本目录
|
||||
LOCK_FILE="${SCRIPT_DIR}/script.lock" # 锁文件
|
||||
|
||||
@@ -84,7 +81,7 @@ DB_PASS="your_password"
|
||||
|
||||
```bash
|
||||
# 启动所有服务(持续运行模式)
|
||||
./start_services.sh
|
||||
./control_scripts.sh startall
|
||||
|
||||
# 查看服务状态
|
||||
./control_scripts.sh statusall
|
||||
@@ -92,7 +89,7 @@ DB_PASS="your_password"
|
||||
|
||||
#### 持续运行模式说明
|
||||
|
||||
- **启动方式**: `./start_services.sh` 一次性启动所有服务
|
||||
- **启动方式**: `./control_scripts.sh startall` 一次性启动所有服务
|
||||
- **运行逻辑**: 每个脚本启动后进入while循环,持续监控和处理数据
|
||||
- **处理周期**: 检查数据库 → 处理未处理记录 → 等待10分钟 → 重复循环
|
||||
- **并发控制**: 通过锁文件确保同一脚本只运行一个实例
|
||||
@@ -114,10 +111,10 @@ DB_PASS="your_password"
|
||||
|
||||
```bash
|
||||
# 正常停止所有服务
|
||||
./stop_services.sh
|
||||
./control_scripts.sh stopall
|
||||
|
||||
# 强制停止所有服务(如果正常停止失败)
|
||||
./stop_services.sh force
|
||||
# 手动kill进程或使用系统命令
|
||||
```
|
||||
|
||||
### 5. 健康检查
|
||||
@@ -187,7 +184,7 @@ DB_PASS="your_password"
|
||||
## 📝 日志说明
|
||||
|
||||
### 日志文件位置
|
||||
- 日志目录:`/var/log/student_status_change/`
|
||||
- 日志目录:`./student_status_change/`
|
||||
- 日志格式:`process_student_changes_YYYYMMDD_HHMMSS.log`
|
||||
|
||||
### 日志内容
|
||||
@@ -268,9 +265,9 @@ rm -f pids/*.pid
|
||||
|
||||
脚本采用持续运行模式,启动后自动循环执行:
|
||||
|
||||
1. **启动脚本**: `./start_services.sh`
|
||||
1. **启动脚本**: `./control_scripts.sh startall`
|
||||
2. **处理逻辑**: 检查未处理的记录 → 处理业务 → 等待10分钟 → 重复
|
||||
3. **停止脚本**: `./stop_services.sh`
|
||||
3. **停止脚本**: `./control_scripts.sh stopall`
|
||||
|
||||
### 可选的定时任务模式
|
||||
|
||||
@@ -286,7 +283,7 @@ crontab -e
|
||||
|
||||
| 特性 | 持续运行模式 | Crontab模式 |
|
||||
|------|-------------|-------------|
|
||||
| 启动方式 | `./start_services.sh` | crontab配置 |
|
||||
| 启动方式 | `./control_scripts.sh startall` | crontab配置 |
|
||||
| 执行频率 | 每10分钟自动 | 可自定义时间 |
|
||||
| 资源占用 | 常驻进程 | 按需启动 |
|
||||
| 监控便利性 | 更容易监控 | 需要额外配置 |
|
||||
@@ -297,16 +294,15 @@ crontab -e
|
||||
## 🚀 快速开始
|
||||
|
||||
### 💡 使用指南
|
||||
1. **查看演示**: 运行 `./demo.sh` 查看脚本使用说明
|
||||
2. **配置数据库**: 编辑 `data.conf` 配置数据库连接信息
|
||||
3. **启动服务**: 使用 `./start_services.sh` 启动持续运行的服务
|
||||
4. **监控运行**: 使用 `./health_check.sh` 检查服务状态
|
||||
5. **停止服务**: 需要时使用 `./stop_services.sh` 停止服务
|
||||
1. **配置数据库**: 编辑 `data.conf` 配置数据库连接信息
|
||||
2. **启动服务**: 使用 `./control_scripts.sh startall` 启动持续运行的服务
|
||||
3. **监控运行**: 使用 `./health_check.sh` 检查服务状态
|
||||
4. **停止服务**: 需要时使用 `./control_scripts.sh stopall` 停止服务
|
||||
|
||||
### 🧪 测试步骤
|
||||
1. **插入测试数据**: 执行 `test_data.sql` 插入测试记录
|
||||
2. **启动服务**: `./start_services.sh`
|
||||
3. **观察日志**: 查看 `/var/log/student_status_change/` 目录的日志
|
||||
2. **启动服务**: `./control_scripts.sh startall`
|
||||
3. **观察日志**: 查看 `./student_status_change/` 目录的日志
|
||||
4. **检查结果**: 确认 `xg_student_status_change.process_status` 已更新为1
|
||||
|
||||
---
|
||||
|
||||
@@ -12,7 +12,7 @@ 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!"
|
||||
echo "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -57,7 +57,7 @@ is_running() {
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
return 0 # Running
|
||||
else
|
||||
log "WARN" "Removing stale PID file for $script_name"
|
||||
log "WARN" "删除脚本 $script_name 的过期PID文件"
|
||||
rm -f "$pid_file"
|
||||
fi
|
||||
fi
|
||||
@@ -68,7 +68,7 @@ is_running() {
|
||||
if kill -0 "$lock_pid" 2>/dev/null; then
|
||||
return 0 # Running
|
||||
else
|
||||
log "WARN" "Removing stale lock file for $script_name"
|
||||
log "WARN" "删除脚本 $script_name 的过期锁定文件"
|
||||
rm -f "$lock_file"
|
||||
fi
|
||||
fi
|
||||
@@ -82,16 +82,16 @@ start_script() {
|
||||
local pid_file=$(get_pid_file "$script_name")
|
||||
|
||||
if [[ ! -f "$script_file" ]]; then
|
||||
log "ERROR" "Script file not found: $script_file"
|
||||
log "ERROR" "脚本文件未找到: $script_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if is_running "$script_name"; then
|
||||
log "INFO" "$script_name is already running"
|
||||
log "INFO" "$script_name 已在运行"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "INFO" "Starting $script_name..."
|
||||
log "INFO" "正在启动 $script_name..."
|
||||
chmod +x "$script_file"
|
||||
|
||||
# Start script in background
|
||||
@@ -103,10 +103,10 @@ start_script() {
|
||||
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
echo $pid > "$pid_file"
|
||||
log "INFO" "$script_name started successfully (PID: $pid)"
|
||||
log "INFO" "$script_name 启动成功 (PID: $pid)"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "Failed to start $script_name"
|
||||
log "ERROR" "$script_name 启动失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -117,30 +117,30 @@ stop_script() {
|
||||
local lock_file=$(get_lock_file "$script_name")
|
||||
local stopped=false
|
||||
|
||||
log "INFO" "Stopping $script_name..."
|
||||
log "INFO" "正在停止 $script_name..."
|
||||
|
||||
# Try to stop by PID file
|
||||
# 尝试通过PID文件停止
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
local pid=$(cat "$pid_file")
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid"
|
||||
sleep 2
|
||||
if ! kill -0 "$pid" 2>/dev/null; then
|
||||
log "INFO" "$script_name stopped successfully (PID: $pid)"
|
||||
log "INFO" "$script_name 停止成功 (PID: $pid)"
|
||||
stopped=true
|
||||
fi
|
||||
fi
|
||||
rm -f "$pid_file"
|
||||
fi
|
||||
|
||||
# Try to stop by lock file
|
||||
# 尝试通过锁定文件停止
|
||||
if [[ -f "$lock_file" ]]; then
|
||||
local lock_pid=$(cat "$lock_file")
|
||||
if kill -0 "$lock_pid" 2>/dev/null; then
|
||||
kill "$lock_pid"
|
||||
sleep 2
|
||||
if ! kill -0 "$lock_pid" 2>/dev/null; then
|
||||
log "INFO" "$script_name stopped successfully (PID: $lock_pid)"
|
||||
log "INFO" "$script_name 停止成功 (PID: $lock_pid)"
|
||||
stopped=true
|
||||
fi
|
||||
fi
|
||||
@@ -148,13 +148,13 @@ stop_script() {
|
||||
fi
|
||||
|
||||
if [[ "$stopped" == false ]]; then
|
||||
log "WARN" "$script_name may not have been running or failed to stop gracefully"
|
||||
log "WARN" "$script_name 可能未运行或优雅停止失败"
|
||||
fi
|
||||
}
|
||||
|
||||
restart_script() {
|
||||
local script_name="$1"
|
||||
log "INFO" "Restarting $script_name..."
|
||||
log "INFO" "正在重启 $script_name..."
|
||||
stop_script "$script_name"
|
||||
sleep 3
|
||||
start_script "$script_name"
|
||||
@@ -168,43 +168,43 @@ status_script() {
|
||||
|
||||
if [[ -f "$pid_file" ]]; then
|
||||
local pid=$(cat "$pid_file")
|
||||
log "INFO" "$script_name is running (PID: $pid)"
|
||||
log "INFO" "$script_name 正在运行 (PID: $pid)"
|
||||
elif [[ -f "$lock_file" ]]; then
|
||||
local lock_pid=$(cat "$lock_file")
|
||||
log "INFO" "$script_name is running (PID: $lock_pid)"
|
||||
log "INFO" "$script_name 正在运行 (PID: $lock_pid)"
|
||||
else
|
||||
log "INFO" "$script_name status unknown"
|
||||
log "INFO" "$script_name 状态未知"
|
||||
fi
|
||||
else
|
||||
log "INFO" "$script_name is not running"
|
||||
log "INFO" "$script_name 未运行"
|
||||
fi
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
cat << EOF
|
||||
Usage: $0 <command> <script_name>
|
||||
用法: $0 <命令> <脚本名称>
|
||||
|
||||
Commands:
|
||||
start Start the specified script
|
||||
stop Stop the specified script
|
||||
restart Restart the specified script
|
||||
status Show status of the specified script
|
||||
startall Start all scripts
|
||||
stopall Stop all scripts
|
||||
statusall Show status of all scripts
|
||||
命令:
|
||||
start 启动指定的脚本
|
||||
stop 停止指定的脚本
|
||||
restart 重启指定的脚本
|
||||
status 显示指定脚本的状态
|
||||
startall 启动所有脚本
|
||||
stopall 停止所有脚本
|
||||
statusall 显示所有脚本的状态
|
||||
|
||||
Script names:
|
||||
changes Student status changes script (休学/退学/毕业)
|
||||
resume Student resume script (复学)
|
||||
all All scripts
|
||||
脚本名称:
|
||||
changes 学生状态变更脚本 (休学/退学/毕业)
|
||||
resume 学生复学脚本 (复学)
|
||||
all 所有脚本
|
||||
|
||||
Examples:
|
||||
$0 start changes # Start changes processing script
|
||||
$0 stop resume # Stop resume processing script
|
||||
$0 restart changes # Restart changes processing script
|
||||
$0 status all # Show status of all scripts
|
||||
$0 startall # Start all scripts
|
||||
$0 stopall # Stop all scripts
|
||||
示例:
|
||||
$0 start changes # 启动状态变更处理脚本
|
||||
$0 stop resume # 停止复学处理脚本
|
||||
$0 restart changes # 重启状态变更处理脚本
|
||||
$0 status all # 显示所有脚本的状态
|
||||
$0 startall # 启动所有脚本
|
||||
$0 stopall # 停止所有脚本
|
||||
|
||||
EOF
|
||||
}
|
||||
@@ -223,7 +223,7 @@ main() {
|
||||
elif [[ -n "${SCRIPTS[$script_name]}" ]]; then
|
||||
start_script "$script_name"
|
||||
else
|
||||
log "ERROR" "Unknown script name: $script_name"
|
||||
log "ERROR" "未知的脚本名称: $script_name"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
@@ -237,7 +237,7 @@ main() {
|
||||
elif [[ -n "${SCRIPTS[$script_name]}" ]]; then
|
||||
stop_script "$script_name"
|
||||
else
|
||||
log "ERROR" "Unknown script name: $script_name"
|
||||
log "ERROR" "未知的脚本名称: $script_name"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
@@ -251,7 +251,7 @@ main() {
|
||||
elif [[ -n "${SCRIPTS[$script_name]}" ]]; then
|
||||
restart_script "$script_name"
|
||||
else
|
||||
log "ERROR" "Unknown script name: $script_name"
|
||||
log "ERROR" "未知的脚本名称: $script_name"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
@@ -265,35 +265,35 @@ main() {
|
||||
elif [[ -n "${SCRIPTS[$script_name]}" ]]; then
|
||||
status_script "$script_name"
|
||||
else
|
||||
log "ERROR" "Unknown script name: $script_name"
|
||||
log "ERROR" "未知的脚本名称: $script_name"
|
||||
show_usage
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
startall)
|
||||
log "INFO" "Starting all scripts..."
|
||||
log "INFO" "正在启动所有脚本..."
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
start_script "$script"
|
||||
done
|
||||
;;
|
||||
|
||||
stopall)
|
||||
log "INFO" "Stopping all scripts..."
|
||||
log "INFO" "正在停止所有脚本..."
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
stop_script "$script"
|
||||
done
|
||||
;;
|
||||
|
||||
statusall)
|
||||
log "INFO" "Checking status of all scripts..."
|
||||
log "INFO" "正在检查所有脚本的状态..."
|
||||
for script in "${!SCRIPTS[@]}"; do
|
||||
status_script "$script"
|
||||
done
|
||||
;;
|
||||
|
||||
*)
|
||||
log "ERROR" "Unknown command: $command"
|
||||
log "ERROR" "未知命令: $command"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Database configuration
|
||||
DB_HOST="localhost"
|
||||
DB_HOST="47.99.164.66"
|
||||
DB_PORT="3306"
|
||||
DB_NAME="hzdyjs_xg"
|
||||
DB_USER="root"
|
||||
DB_PASS="password"
|
||||
DB_PASS="hn02le.34lkdLKD"
|
||||
|
||||
# Script configuration
|
||||
LOG_DIR="/var/log/student_status_change"
|
||||
LOG_DIR="${SCRIPT_DIR}/student_status_change"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOCK_FILE="${SCRIPT_DIR}/script.lock"
|
||||
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生状态变更处理脚本演示
|
||||
# 展示如何使用这些脚本
|
||||
# ===========================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
echo "========================================"
|
||||
echo " 学生状态变更处理脚本演示"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
echo "脚本位置: $SCRIPT_DIR"
|
||||
echo ""
|
||||
|
||||
echo "📋 脚本文件说明:"
|
||||
echo " process_student_changes.sh - 处理毕业/退学/休学的状态变更"
|
||||
echo " process_student_resume.sh - 处理复学的状态变更"
|
||||
echo " control_scripts.sh - 脚本控制程序"
|
||||
echo " start_services.sh - 一键启动所有服务"
|
||||
echo " stop_services.sh - 一键停止所有服务"
|
||||
echo " health_check.sh - 服务健康检查"
|
||||
echo ""
|
||||
|
||||
echo "🔧 配置文件:"
|
||||
echo " data.conf - 数据库配置"
|
||||
echo " test_data.sql - 测试数据"
|
||||
echo ""
|
||||
|
||||
echo "📖 使用步骤:"
|
||||
echo ""
|
||||
|
||||
echo "1️⃣ 配置数据库连接:"
|
||||
echo " vim data.conf"
|
||||
echo " # 修改数据库连接信息"
|
||||
echo ""
|
||||
|
||||
echo "2️⃣ 启动服务(持续运行模式):"
|
||||
echo " ./start_services.sh"
|
||||
echo ""
|
||||
|
||||
echo "3️⃣ 查看服务状态:"
|
||||
echo " ./control_scripts.sh statusall"
|
||||
echo ""
|
||||
|
||||
echo "4️⃣ 执行健康检查:"
|
||||
echo " ./health_check.sh"
|
||||
echo ""
|
||||
|
||||
echo "5️⃣ 停止服务:"
|
||||
echo " ./stop_services.sh"
|
||||
echo ""
|
||||
|
||||
echo "📊 运行模式说明:"
|
||||
echo "• 脚本启动后进入持续运行模式"
|
||||
echo "• 每10分钟自动检查和处理一次数据"
|
||||
echo "• 支持并发控制,避免重复运行"
|
||||
echo "• 完整的日志记录和错误处理"
|
||||
echo ""
|
||||
|
||||
echo "🧪 测试数据:"
|
||||
echo "• 运行 test_data.sql 插入测试数据"
|
||||
echo "• 脚本会自动处理 process_status = 0 的记录"
|
||||
echo ""
|
||||
|
||||
echo "📝 日志位置:"
|
||||
echo "• /var/log/student_status_change/"
|
||||
echo "• 包含详细的处理日志和错误信息"
|
||||
echo ""
|
||||
|
||||
echo "⚠️ 注意事项:"
|
||||
echo "• 确保数据库连接正确"
|
||||
echo "• 确保用户有足够的数据库权限"
|
||||
echo "• 定期检查日志文件"
|
||||
echo "• 监控磁盘空间使用情况"
|
||||
echo ""
|
||||
|
||||
echo "========================================"
|
||||
echo " 演示完成"
|
||||
echo "========================================"
|
||||
+41
-41
@@ -20,7 +20,7 @@ NC='\033[0m' # No Color
|
||||
|
||||
# Load configuration
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo -e "${RED}Error: Configuration file $CONFIG_FILE not found!${NC}"
|
||||
echo -e "${RED}错误:配置文件 $CONFIG_FILE 未找到!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -50,34 +50,34 @@ info() {
|
||||
echo -e "${BLUE}ℹ $1${NC}"
|
||||
}
|
||||
|
||||
# Check database connection
|
||||
# 检查数据库连接
|
||||
check_database() {
|
||||
info "Checking database connection..."
|
||||
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 "Database connection successful"
|
||||
success "数据库连接成功"
|
||||
return 0
|
||||
else
|
||||
error "Database query failed"
|
||||
error "数据库查询失败"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
error "Database connection failed"
|
||||
error "数据库连接失败"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check service status
|
||||
# 检查服务状态
|
||||
check_service() {
|
||||
local service_name="$1"
|
||||
local service_desc="$2"
|
||||
|
||||
info "Checking $service_desc..."
|
||||
info "正在检查 $service_desc..."
|
||||
|
||||
if [[ ! -x "$CONTROL_SCRIPT" ]]; then
|
||||
error "Control script not found or not executable: $CONTROL_SCRIPT"
|
||||
error "控制脚本未找到或不可执行: $CONTROL_SCRIPT"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -85,58 +85,58 @@ check_service() {
|
||||
status_output=$("$CONTROL_SCRIPT" status "$service_name" 2>/dev/null)
|
||||
|
||||
if echo "$status_output" | grep -q "is running"; then
|
||||
success "$service_desc is running"
|
||||
success "$service_desc 正在运行"
|
||||
|
||||
# Extract PID if available
|
||||
# 提取PID(如果可用)
|
||||
local pid
|
||||
pid=$(echo "$status_output" | grep -o "PID: [0-9]*" | cut -d' ' -f2)
|
||||
if [[ -n "$pid" ]]; then
|
||||
info " Process ID: $pid"
|
||||
info " 进程ID: $pid"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
error "$service_desc is not running"
|
||||
error "$service_desc 未运行"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check log files
|
||||
# 检查日志文件
|
||||
check_logs() {
|
||||
info "Checking log files..."
|
||||
info "正在检查日志文件..."
|
||||
|
||||
if [[ ! -d "$LOG_DIR" ]]; then
|
||||
warning "Log directory does not exist: $LOG_DIR"
|
||||
warning "日志目录不存在: $LOG_DIR"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Count log files
|
||||
# 统计日志文件数量
|
||||
local log_count
|
||||
log_count=$(find "$LOG_DIR" -name "*.log" -type f | wc -l)
|
||||
|
||||
if [[ $log_count -gt 0 ]]; then
|
||||
success "Found $log_count log files"
|
||||
success "发现 $log_count 个日志文件"
|
||||
|
||||
# Check for recent errors
|
||||
# 检查最近的错误
|
||||
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 "Found $recent_errors log files with recent errors (last 60 minutes)"
|
||||
warning "发现 $recent_errors 个日志文件包含最近的错误 (最近60分钟)"
|
||||
else
|
||||
info "No recent errors found in log files"
|
||||
info "日志文件中未发现最近的错误"
|
||||
fi
|
||||
|
||||
return 0
|
||||
else
|
||||
warning "No log files found"
|
||||
warning "未发现日志文件"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check pending records
|
||||
# 检查待处理记录
|
||||
check_pending_records() {
|
||||
info "Checking pending records in database..."
|
||||
info "正在检查数据库中的待处理记录..."
|
||||
|
||||
local pending_changes pending_resume
|
||||
|
||||
@@ -171,39 +171,39 @@ check_pending_records() {
|
||||
local total_pending=$((pending_changes + pending_resume))
|
||||
|
||||
if [[ $total_pending -gt 0 ]]; then
|
||||
info "Found $total_pending pending records ($pending_changes changes, $pending_resume resume)"
|
||||
info "发现 $total_pending 条待处理记录 ($pending_changes 条变更, $pending_resume 条复学)"
|
||||
if [[ $pending_changes -gt 0 ]]; then
|
||||
warning " $pending_changes records waiting for changes processing"
|
||||
warning " $pending_changes 条记录等待变更处理"
|
||||
fi
|
||||
if [[ $pending_resume -gt 0 ]]; then
|
||||
warning " $pending_resume records waiting for resume processing"
|
||||
warning " $pending_resume 条记录等待复学处理"
|
||||
fi
|
||||
else
|
||||
success "No pending records found"
|
||||
success "未发现待处理记录"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check disk space
|
||||
# 检查磁盘空间
|
||||
check_disk_space() {
|
||||
info "Checking 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 "Cannot determine log directory disk usage"
|
||||
warning "无法确定日志目录的磁盘使用情况"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ $log_disk_usage -gt 90 ]]; then
|
||||
error "Log directory disk usage is ${log_disk_usage}% - consider cleaning up old logs"
|
||||
error "日志目录磁盘使用率达到 ${log_disk_usage}% - 建议清理旧日志"
|
||||
return 1
|
||||
elif [[ $log_disk_usage -gt 75 ]]; then
|
||||
warning "Log directory disk usage is ${log_disk_usage}%"
|
||||
warning "日志目录磁盘使用率达到 ${log_disk_usage}%"
|
||||
else
|
||||
success "Log directory disk usage is ${log_disk_usage}%"
|
||||
success "日志目录磁盘使用率 ${log_disk_usage}%"
|
||||
fi
|
||||
|
||||
return 0
|
||||
@@ -267,9 +267,9 @@ generate_report() {
|
||||
} > "$report_file" 2>/dev/null
|
||||
|
||||
if [[ -f "$report_file" ]]; then
|
||||
success "Health check report generated: $report_file"
|
||||
success "健康检查报告已生成: $report_file"
|
||||
else
|
||||
error "Failed to generate health check report"
|
||||
error "生成健康检查报告失败"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ main() {
|
||||
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " 学生状态变更处理服务健康检查"
|
||||
echo " 学生状态变更处理服务健康检查"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
@@ -320,14 +320,14 @@ main() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Show usage
|
||||
# 显示使用方法
|
||||
show_usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [report]
|
||||
用法: $0 [report]
|
||||
|
||||
执行学生状态变更处理服务的健康检查。
|
||||
|
||||
Options:
|
||||
选项:
|
||||
report 生成详细的健康检查报告
|
||||
|
||||
检查内容:
|
||||
@@ -352,7 +352,7 @@ case "${1:-}" in
|
||||
main
|
||||
;;
|
||||
*)
|
||||
error "Unknown option: $1"
|
||||
error "未知选项: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
|
||||
@@ -12,7 +12,7 @@ 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!"
|
||||
echo "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -43,13 +43,13 @@ error_exit() {
|
||||
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"))"
|
||||
log "INFO" "脚本已在运行 (PID: $(cat "$LOCK_FILE"))"
|
||||
exit 1
|
||||
else
|
||||
log "WARN" "Removing stale lock file"
|
||||
log "WARN" "删除过期的锁定文件"
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
fi
|
||||
@@ -57,10 +57,10 @@ fi
|
||||
# Create lock file
|
||||
echo $$ > "$LOCK_FILE"
|
||||
|
||||
# Cleanup function
|
||||
# 清理函数
|
||||
cleanup() {
|
||||
[[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE"
|
||||
log "INFO" "Script execution completed"
|
||||
log "INFO" "脚本执行完成"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
@@ -74,8 +74,8 @@ execute_sql() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
log "ERROR" "SQL execution failed: $sql"
|
||||
log "ERROR" "MySQL error: $result"
|
||||
log "ERROR" "SQL执行失败: $sql"
|
||||
log "ERROR" "MySQL错误: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -90,19 +90,54 @@ process_student_change() {
|
||||
local change_type="$4"
|
||||
local operator_id="${5:-1}"
|
||||
|
||||
log "INFO" "Processing student change - ID: $record_id, Student: $student_no ($student_id), Type: $change_type"
|
||||
|
||||
log "INFO" "正在处理学生状态变更 - ID: $record_id, 学生: $student_no ($student_id), 类型: $change_type"
|
||||
|
||||
# Get dormitory assignment info before transaction
|
||||
local dorm_query="
|
||||
SELECT GROUP_CONCAT(id), GROUP_CONCAT(bed_id)
|
||||
FROM xg_dorm_bed_student
|
||||
WHERE student_id = $student_id AND status = '0' AND deleted = 0;
|
||||
"
|
||||
|
||||
local dorm_info=""
|
||||
local dorm_ids=""
|
||||
local bed_ids=""
|
||||
|
||||
# Execute dormitory query with error handling
|
||||
if dorm_info=$(execute_sql "$dorm_query" 2>/dev/null); then
|
||||
# Parse the result (skip header if present)
|
||||
if [[ -n "$dorm_info" ]]; then
|
||||
# Remove warnings, keep only data rows
|
||||
dorm_info=$(echo "$dorm_info" | grep -v "mysql:" | grep -E "^[0-9]+\t" | head -n 1)
|
||||
if [[ -n "$dorm_info" && "$dorm_info" != "NULL" && "$dorm_info" != "NULL\tNULL" ]]; then
|
||||
# Split by tab and handle NULL values
|
||||
IFS=$'\t' read -r dorm_ids_raw bed_ids_raw <<< "$dorm_info"
|
||||
if [[ "$dorm_ids_raw" != "NULL" && -n "$dorm_ids_raw" ]]; then
|
||||
dorm_ids="$dorm_ids_raw"
|
||||
fi
|
||||
if [[ "$bed_ids_raw" != "NULL" && -n "$bed_ids_raw" ]]; then
|
||||
bed_ids="$bed_ids_raw"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log "WARN" "查询宿舍分配信息失败,将跳过宿舍处理 - 学生ID: $student_id"
|
||||
fi
|
||||
|
||||
log "INFO" "找到宿舍分配 - ID: ${dorm_ids:-无}, 床位: ${bed_ids:-无}"
|
||||
|
||||
# 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;
|
||||
INSERT INTO xg_class_pos_msg_his SELECT * FROM xg_class_pos_msg WHERE student_id = $student_id;
|
||||
INSERT INTO club_member_his SELECT * FROM club_member WHERE user_id = $student_id;
|
||||
INSERT INTO stgl_member_his SELECT * FROM stgl_member WHERE user_id = $student_id;
|
||||
INSERT INTO xg_dorm_bed_student_his SELECT * FROM xg_dorm_bed_student WHERE student_id = $student_id;
|
||||
-- 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';
|
||||
INSERT IGNORE INTO xg_class_pos_msg_his SELECT * FROM xg_class_pos_msg WHERE student_id = '$student_id';
|
||||
INSERT IGNORE INTO club_member_his SELECT * FROM club_member WHERE user_id = '$student_id';
|
||||
INSERT IGNORE INTO stgl_member_his SELECT * FROM stgl_member WHERE user_id = '$student_id';
|
||||
INSERT IGNORE INTO xg_dorm_bed_student_his SELECT * FROM xg_dorm_bed_student WHERE student_id = '$student_id';
|
||||
|
||||
-- 2. Update student status
|
||||
UPDATE xg_student_msg SET
|
||||
@@ -112,16 +147,16 @@ process_student_change() {
|
||||
WHEN '$change_type' = 'BI_YE' THEN '5'
|
||||
ELSE student_status
|
||||
END,
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE id = $student_id;
|
||||
WHERE id = '$student_id';
|
||||
|
||||
-- 3. Disable user account
|
||||
UPDATE sys_user SET
|
||||
status = '1',
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE user_id = $student_id AND account_type = '2';
|
||||
WHERE user_id = '$student_id' AND account_type = '2';
|
||||
|
||||
-- 4. Process class position (cadre) - only for XIU_XUE, TUI_XUE, BI_YE
|
||||
UPDATE xg_class_pos_msg SET
|
||||
@@ -140,98 +175,101 @@ process_student_change() {
|
||||
END,
|
||||
term_end_date = CURDATE(),
|
||||
term_duration = TIMESTAMPDIFF(MONTH, term_start_date, CURDATE()),
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE student_id = $student_id AND is_current = 1;
|
||||
WHERE student_id = '$student_id' AND is_current = 1;
|
||||
|
||||
-- 5. Process club membership - only for XIU_XUE, TUI_XUE, BI_YE
|
||||
UPDATE club_member SET
|
||||
member_status = '4',
|
||||
update_by = $operator_id,
|
||||
update_time = NOW(),
|
||||
remark = CONCAT(COALESCE(remark, ''), ' | 退出原因:',
|
||||
CASE
|
||||
WHEN '$change_type' = 'XIU_XUE' THEN '学生休学'
|
||||
WHEN '$change_type' = 'TUI_XUE' THEN '学生退学'
|
||||
WHEN '$change_type' = 'BI_YE' THEN '学生毕业'
|
||||
ELSE '学生状态变更'
|
||||
END, ' - ', NOW())
|
||||
WHERE user_id = $student_id AND member_status IN ('0', '1', '2');
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE user_id = '$student_id' AND member_status IN ('0', '1', '2');
|
||||
|
||||
-- 6. Process volunteer membership - only for XIU_XUE, TUI_XUE, BI_YE
|
||||
UPDATE stgl_member SET
|
||||
status = 4,
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE user_id = $student_id AND status IN (0, 1, 2);
|
||||
WHERE user_id = '$student_id' AND status IN (0, 1, 2);
|
||||
|
||||
-- 7. Process dormitory - only for TUI_XUE, BI_YE
|
||||
-- First, clear dormitory info from student record
|
||||
UPDATE xg_student_msg SET
|
||||
dormitory_building = NULL,
|
||||
dormitory_room = NULL,
|
||||
ext_field1 = NULL,
|
||||
update_time = NOW(),
|
||||
update_by = $operator_id
|
||||
WHERE id = $student_id;
|
||||
update_by = '$operator_id'
|
||||
WHERE id = '$student_id';"
|
||||
|
||||
# Add dormitory processing only if assignments exist and are valid
|
||||
if [[ -n "$dorm_ids" && "$dorm_ids" != "NULL" && -n "$bed_ids" && "$bed_ids" != "NULL" ]]; then
|
||||
transaction_sql+="
|
||||
-- Process dormitory checkout for specific assignments
|
||||
UPDATE xg_dorm_bed_student SET
|
||||
status = '1',
|
||||
checkout_time = NOW(),
|
||||
update_time = NOW(),
|
||||
update_by = $operator_id
|
||||
WHERE student_id = $student_id AND status = '0';
|
||||
update_by = '$operator_id'
|
||||
WHERE FIND_IN_SET(id, '$dorm_ids') AND deleted = 0;
|
||||
|
||||
-- Update bed status for specific beds
|
||||
UPDATE xg_dorm_bed SET
|
||||
bed_status = '0'
|
||||
WHERE id IN (
|
||||
SELECT bed_id FROM xg_dorm_bed_student
|
||||
WHERE student_id = $student_id AND status = '1'
|
||||
);
|
||||
WHERE FIND_IN_SET(id, '$bed_ids') AND deleted = 0;"
|
||||
log "INFO" "将处理宿舍退宿 - 分配ID: $dorm_ids, 床位ID: $bed_ids"
|
||||
else
|
||||
log "INFO" "无需处理宿舍退宿(无有效宿舍分配)"
|
||||
fi
|
||||
|
||||
transaction_sql+="
|
||||
|
||||
-- 8. Update change record status
|
||||
UPDATE xg_student_status_change SET
|
||||
process_status = 1,
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE id = $record_id;
|
||||
WHERE id = '$record_id';
|
||||
|
||||
COMMIT;
|
||||
"
|
||||
|
||||
# Execute transaction
|
||||
# 执行事务
|
||||
if execute_sql "$transaction_sql"; then
|
||||
log "INFO" "Successfully processed student change - ID: $record_id, Student: $student_no"
|
||||
log "INFO" "成功处理学生状态变更 - ID: $record_id, 学生: $student_no"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "Failed to process student change - ID: $record_id, Student: $student_no"
|
||||
log "ERROR" "处理学生状态变更失败 - ID: $record_id, 学生: $student_no"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
log "INFO" "Starting student status change processing daemon"
|
||||
log "INFO" "Processing types: XIU_XUE(休学), TUI_XUE(退学), BI_YE(毕业)"
|
||||
log "INFO" "Running in continuous mode with 10-minute intervals"
|
||||
log "INFO" "启动学生状态变更处理守护进程"
|
||||
log "INFO" "处理类型: XIU_XUE(休学), TUI_XUE(退学), BI_YE(毕业)"
|
||||
log "INFO" "以连续模式运行,间隔10分钟"
|
||||
|
||||
# Test database connection
|
||||
log "INFO" "Testing database connection..."
|
||||
# 测试数据库连接
|
||||
log "INFO" "正在测试数据库连接..."
|
||||
if ! execute_sql "SELECT 1;" >/dev/null 2>&1; then
|
||||
error_exit "Database connection failed"
|
||||
error_exit "数据库连接失败"
|
||||
fi
|
||||
log "INFO" "Database connection successful"
|
||||
log "INFO" "数据库连接成功"
|
||||
|
||||
# Main processing loop
|
||||
while true; do
|
||||
log "INFO" "Starting new processing cycle"
|
||||
log "INFO" "开始新的处理周期"
|
||||
|
||||
# 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 IN ('XIU_XUE', 'TUI_XUE', 'BI_YE')
|
||||
AND deleted = 0
|
||||
AND effective_date <= NOW()
|
||||
ORDER BY create_time ASC
|
||||
LIMIT $BATCH_SIZE;
|
||||
"
|
||||
@@ -239,15 +277,17 @@ main() {
|
||||
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 records found, waiting..."
|
||||
log "INFO" "未找到未处理的记录,正在等待..."
|
||||
else
|
||||
# Remove header line
|
||||
records=$(echo "$records" | tail -n +2)
|
||||
# 移除标题行和可能的警告信息
|
||||
records=$(echo "$records" | grep -v "mysql:" | grep -v "id\t" | grep -v "^$")
|
||||
|
||||
|
||||
local processed_count=0
|
||||
local failed_count=0
|
||||
@@ -257,6 +297,7 @@ main() {
|
||||
# Skip empty lines
|
||||
[[ -z "$record_id" ]] && continue
|
||||
|
||||
|
||||
local retry_count=0
|
||||
local success=false
|
||||
|
||||
@@ -267,7 +308,7 @@ main() {
|
||||
else
|
||||
((retry_count++))
|
||||
if [[ $retry_count -lt $MAX_RETRY ]]; then
|
||||
log "WARN" "Processing failed, retrying in $RETRY_DELAY seconds... (attempt $retry_count/$MAX_RETRY)"
|
||||
log "WARN" "处理失败,$RETRY_DELAY 秒后重试... (尝试 $retry_count/$MAX_RETRY)"
|
||||
sleep $RETRY_DELAY
|
||||
fi
|
||||
fi
|
||||
@@ -275,16 +316,16 @@ main() {
|
||||
|
||||
if [[ $success == false ]]; then
|
||||
((failed_count++))
|
||||
log "ERROR" "Failed to process record after $MAX_RETRY attempts - ID: $record_id"
|
||||
log "ERROR" "$MAX_RETRY 次尝试后仍处理失败 - ID: $record_id"
|
||||
fi
|
||||
|
||||
done <<< "$records"
|
||||
|
||||
log "INFO" "Processing cycle completed - Processed: $processed_count, Failed: $failed_count"
|
||||
log "INFO" "处理周期完成 - 已处理: $processed_count, 失败: $failed_count"
|
||||
fi
|
||||
|
||||
# Wait for configured interval before next cycle
|
||||
log "INFO" "Waiting $CYCLE_INTERVAL seconds before next processing cycle..."
|
||||
# 等待配置的间隔时间后开始下一个周期
|
||||
log "INFO" "等待 $CYCLE_INTERVAL 秒后开始下一个处理周期..."
|
||||
sleep $CYCLE_INTERVAL
|
||||
done
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ 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!"
|
||||
echo "错误:配置文件 $CONFIG_FILE 未找到!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -43,13 +43,13 @@ error_exit() {
|
||||
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"))"
|
||||
log "INFO" "脚本已在运行 (PID: $(cat "$LOCK_FILE"))"
|
||||
exit 1
|
||||
else
|
||||
log "WARN" "Removing stale lock file"
|
||||
log "WARN" "删除过期的锁定文件"
|
||||
rm -f "$LOCK_FILE"
|
||||
fi
|
||||
fi
|
||||
@@ -57,10 +57,10 @@ fi
|
||||
# Create lock file
|
||||
echo $$ > "$LOCK_FILE"
|
||||
|
||||
# Cleanup function
|
||||
# 清理函数
|
||||
cleanup() {
|
||||
[[ -f "$LOCK_FILE" ]] && rm -f "$LOCK_FILE"
|
||||
log "INFO" "Script execution completed"
|
||||
log "INFO" "脚本执行完成"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
@@ -74,8 +74,8 @@ execute_sql() {
|
||||
local exit_code=$?
|
||||
|
||||
if [[ $exit_code -ne 0 ]]; then
|
||||
log "ERROR" "SQL execution failed: $sql"
|
||||
log "ERROR" "MySQL error: $result"
|
||||
log "ERROR" "SQL执行失败: $sql"
|
||||
log "ERROR" "MySQL错误: $result"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -90,74 +90,75 @@ process_student_resume() {
|
||||
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"
|
||||
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
|
||||
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;
|
||||
-- 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 = '3',
|
||||
update_by = $operator_id,
|
||||
student_status = '1',
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE id = $student_id;
|
||||
WHERE id = '$student_id';
|
||||
|
||||
-- 3. Enable user account
|
||||
UPDATE sys_user SET
|
||||
status = '0',
|
||||
update_by = $operator_id,
|
||||
update_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE user_id = $student_id AND account_type = '2';
|
||||
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_by = '$operator_id',
|
||||
update_time = NOW()
|
||||
WHERE id = $record_id;
|
||||
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"
|
||||
log "INFO" "成功处理学生复学 - ID: $record_id, 学生: $student_no"
|
||||
return 0
|
||||
else
|
||||
log "ERROR" "Failed to process student resume - ID: $record_id, Student: $student_no"
|
||||
log "ERROR" "处理学生复学失败 - ID: $record_id, 学生: $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"
|
||||
log "INFO" "启动学生复学处理守护进程"
|
||||
log "INFO" "处理类型: FU_XUE(复学)"
|
||||
log "INFO" "以连续模式运行,间隔10分钟"
|
||||
|
||||
# Test database connection
|
||||
log "INFO" "Testing database connection..."
|
||||
# 测试数据库连接
|
||||
log "INFO" "正在测试数据库连接..."
|
||||
if ! execute_sql "SELECT 1;" >/dev/null 2>&1; then
|
||||
error_exit "Database connection failed"
|
||||
error_exit "数据库连接失败"
|
||||
fi
|
||||
log "INFO" "Database connection successful"
|
||||
log "INFO" "数据库连接成功"
|
||||
|
||||
# Main processing loop
|
||||
while true; do
|
||||
log "INFO" "Starting new resume processing cycle"
|
||||
log "INFO" "开始新的复学处理周期"
|
||||
|
||||
# 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
|
||||
AND effective_date <= NOW()
|
||||
ORDER BY create_time ASC
|
||||
LIMIT $BATCH_SIZE;
|
||||
"
|
||||
@@ -165,15 +166,15 @@ main() {
|
||||
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..."
|
||||
log "INFO" "未找到未处理的复学记录,正在等待..."
|
||||
else
|
||||
# Remove header line
|
||||
records=$(echo "$records" | tail -n +2)
|
||||
# 移除标题行和可能的警告信息
|
||||
records=$(echo "$records" | grep -v "mysql:" | grep -v "id\t" | grep -v "^$")
|
||||
|
||||
local processed_count=0
|
||||
local failed_count=0
|
||||
@@ -193,7 +194,7 @@ main() {
|
||||
else
|
||||
((retry_count++))
|
||||
if [[ $retry_count -lt $MAX_RETRY ]]; then
|
||||
log "WARN" "Processing failed, retrying in $RETRY_DELAY seconds... (attempt $retry_count/$MAX_RETRY)"
|
||||
log "WARN" "处理失败,$RETRY_DELAY 秒后重试... (尝试 $retry_count/$MAX_RETRY)"
|
||||
sleep $RETRY_DELAY
|
||||
fi
|
||||
fi
|
||||
@@ -201,16 +202,16 @@ main() {
|
||||
|
||||
if [[ $success == false ]]; then
|
||||
((failed_count++))
|
||||
log "ERROR" "Failed to process record after $MAX_RETRY attempts - ID: $record_id"
|
||||
log "ERROR" "$MAX_RETRY 次尝试后仍处理失败 - ID: $record_id"
|
||||
fi
|
||||
|
||||
done <<< "$records"
|
||||
|
||||
log "INFO" "Resume processing cycle completed - Processed: $processed_count, Failed: $failed_count"
|
||||
log "INFO" "复学处理周期完成 - 已处理: $processed_count, 失败: $failed_count"
|
||||
fi
|
||||
|
||||
# Wait for configured interval before next cycle
|
||||
log "INFO" "Waiting $CYCLE_INTERVAL seconds before next resume processing cycle..."
|
||||
# 等待配置的间隔时间后开始下一个周期
|
||||
log "INFO" "等待 $CYCLE_INTERVAL 秒后开始下一个复学处理周期..."
|
||||
sleep $CYCLE_INTERVAL
|
||||
done
|
||||
}
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生状态变更处理服务启动脚本
|
||||
# 用于启动所有相关的处理服务
|
||||
# ===========================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONTROL_SCRIPT="${SCRIPT_DIR}/control_scripts.sh"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo -e "${timestamp} [$level] $message"
|
||||
}
|
||||
|
||||
success() {
|
||||
log "${GREEN}SUCCESS${NC}" "$1"
|
||||
}
|
||||
|
||||
error() {
|
||||
log "${RED}ERROR${NC}" "$1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
log "${YELLOW}WARNING${NC}" "$1"
|
||||
}
|
||||
|
||||
# Check if control script exists and is executable
|
||||
if [[ ! -x "$CONTROL_SCRIPT" ]]; then
|
||||
error "Control script not found or not executable: $CONTROL_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to start a service
|
||||
start_service() {
|
||||
local service_name="$1"
|
||||
local service_desc="$2"
|
||||
|
||||
log "INFO" "Starting $service_desc..."
|
||||
if "$CONTROL_SCRIPT" start "$service_name"; then
|
||||
success "$service_desc started successfully"
|
||||
return 0
|
||||
else
|
||||
error "Failed to start $service_desc"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check service status
|
||||
check_service() {
|
||||
local service_name="$1"
|
||||
local service_desc="$2"
|
||||
|
||||
log "INFO" "Checking $service_desc status..."
|
||||
if "$CONTROL_SCRIPT" status "$service_name" | grep -q "is running"; then
|
||||
success "$service_desc is running"
|
||||
return 0
|
||||
else
|
||||
warning "$service_desc is not running"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
log "INFO" "=== 学生状态变更处理服务启动脚本 ==="
|
||||
log "INFO" "Starting all student status change processing services..."
|
||||
|
||||
local failed_services=()
|
||||
|
||||
# Start changes processing service
|
||||
if ! start_service "changes" "学生状态变更处理服务 (休学/退学/毕业)"; then
|
||||
failed_services+=("changes")
|
||||
fi
|
||||
|
||||
# Start resume processing service
|
||||
if ! start_service "resume" "学生复学处理服务"; then
|
||||
failed_services+=("resume")
|
||||
fi
|
||||
|
||||
# Wait a moment for services to fully start
|
||||
sleep 3
|
||||
|
||||
log "INFO" "=== 服务状态检查 ==="
|
||||
|
||||
# Check all services status
|
||||
check_service "changes" "学生状态变更处理服务 (休学/退学/毕业)"
|
||||
check_service "resume" "学生复学处理服务"
|
||||
|
||||
# Summary
|
||||
log "INFO" "=== 启动完成 ==="
|
||||
if [[ ${#failed_services[@]} -eq 0 ]]; then
|
||||
success "所有服务启动成功"
|
||||
echo ""
|
||||
echo "服务控制命令:"
|
||||
echo " 查看状态: $CONTROL_SCRIPT statusall"
|
||||
echo " 停止服务: $CONTROL_SCRIPT stopall"
|
||||
echo " 重启服务: $CONTROL_SCRIPT restart changes|resume"
|
||||
echo ""
|
||||
echo "日志文件位置: /var/log/student_status_change/"
|
||||
else
|
||||
error "以下服务启动失败: ${failed_services[*]}"
|
||||
echo ""
|
||||
echo "故障排除:"
|
||||
echo "1. 检查数据库配置: cat data.conf"
|
||||
echo "2. 查看日志文件: tail -f /var/log/student_status_change/*.log"
|
||||
echo "3. 检查数据库连接: mysql -h\$DB_HOST -P\$DB_PORT -u\$DB_USER -p\$DB_PASS \$DB_NAME -e 'SELECT 1;'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
@@ -1,177 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===========================================
|
||||
# 学生状态变更处理服务停止脚本
|
||||
# 用于停止所有相关的处理服务
|
||||
# ===========================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONTROL_SCRIPT="${SCRIPT_DIR}/control_scripts.sh"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log() {
|
||||
local level="$1"
|
||||
local message="$2"
|
||||
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
echo -e "${timestamp} [$level] $message"
|
||||
}
|
||||
|
||||
success() {
|
||||
log "${GREEN}SUCCESS${NC}" "$1"
|
||||
}
|
||||
|
||||
error() {
|
||||
log "${RED}ERROR${NC}" "$1"
|
||||
}
|
||||
|
||||
warning() {
|
||||
log "${YELLOW}WARNING${NC}" "$1"
|
||||
}
|
||||
|
||||
# Check if control script exists and is executable
|
||||
if [[ ! -x "$CONTROL_SCRIPT" ]]; then
|
||||
error "Control script not found or not executable: $CONTROL_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to stop a service
|
||||
stop_service() {
|
||||
local service_name="$1"
|
||||
local service_desc="$2"
|
||||
|
||||
log "INFO" "Stopping $service_desc..."
|
||||
if "$CONTROL_SCRIPT" stop "$service_name"; then
|
||||
success "$service_desc stopped successfully"
|
||||
return 0
|
||||
else
|
||||
warning "$service_desc may not have been running"
|
||||
return 0 # Not treating this as a hard error
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check service status after stop
|
||||
check_service_stopped() {
|
||||
local service_name="$1"
|
||||
local service_desc="$2"
|
||||
|
||||
log "INFO" "Verifying $service_desc has stopped..."
|
||||
if "$CONTROL_SCRIPT" status "$service_name" | grep -q "is not running"; then
|
||||
success "$service_desc confirmed stopped"
|
||||
return 0
|
||||
else
|
||||
warning "$service_desc may still be running"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to force kill if needed
|
||||
force_kill_service() {
|
||||
local service_name="$1"
|
||||
local script_pattern="$2"
|
||||
local service_desc="$3"
|
||||
|
||||
log "INFO" "Force killing $service_desc..."
|
||||
if pkill -f "$script_pattern"; then
|
||||
sleep 2
|
||||
success "$service_desc force killed"
|
||||
return 0
|
||||
else
|
||||
warning "No processes found for $service_desc"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
local force_kill="${1:-false}"
|
||||
|
||||
log "INFO" "=== 学生状态变更处理服务停止脚本 ==="
|
||||
|
||||
if [[ "$force_kill" == "force" ]]; then
|
||||
log "INFO" "Performing force stop of all services..."
|
||||
|
||||
# Force kill all related processes
|
||||
force_kill_service "changes" "process_student_changes.sh" "学生状态变更处理服务"
|
||||
force_kill_service "resume" "process_student_resume.sh" "学生复学处理服务"
|
||||
|
||||
# Clean up lock and PID files
|
||||
log "INFO" "Cleaning up lock and PID files..."
|
||||
rm -f "${SCRIPT_DIR}"/*.lock
|
||||
rm -f "${SCRIPT_DIR}/pids"/*.pid
|
||||
|
||||
success "Force stop completed"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "INFO" "Stopping all student status change processing services..."
|
||||
|
||||
# Stop services gracefully
|
||||
stop_service "changes" "学生状态变更处理服务 (休学/退学/毕业)"
|
||||
stop_service "resume" "学生复学处理服务"
|
||||
|
||||
# Wait a moment for services to fully stop
|
||||
sleep 3
|
||||
|
||||
log "INFO" "=== 服务状态验证 ==="
|
||||
|
||||
# Check all services are stopped
|
||||
check_service_stopped "changes" "学生状态变更处理服务 (休学/退学/毕业)"
|
||||
check_service_stopped "resume" "学生复学处理服务"
|
||||
|
||||
# Final cleanup
|
||||
log "INFO" "Performing final cleanup..."
|
||||
rm -f "${SCRIPT_DIR}"/*.lock 2>/dev/null || true
|
||||
rm -f "${SCRIPT_DIR}/pids"/*.pid 2>/dev/null || true
|
||||
|
||||
log "INFO" "=== 停止完成 ==="
|
||||
success "所有服务已停止"
|
||||
|
||||
echo ""
|
||||
echo "如果服务未能正常停止,请使用强制停止:"
|
||||
echo " $0 force"
|
||||
echo ""
|
||||
echo "重新启动服务:"
|
||||
echo " ./start_services.sh"
|
||||
}
|
||||
|
||||
# Show usage
|
||||
show_usage() {
|
||||
cat << EOF
|
||||
Usage: $0 [force]
|
||||
|
||||
停止所有学生状态变更处理服务。
|
||||
|
||||
Options:
|
||||
force 强制杀死所有相关进程并清理锁文件
|
||||
|
||||
Examples:
|
||||
$0 # 正常停止所有服务
|
||||
$0 force # 强制停止所有服务
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
case "${1:-}" in
|
||||
force)
|
||||
main "force"
|
||||
;;
|
||||
-h|--help)
|
||||
show_usage
|
||||
;;
|
||||
"")
|
||||
main
|
||||
;;
|
||||
*)
|
||||
error "Unknown option: $1"
|
||||
show_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1,104 +0,0 @@
|
||||
-- ===========================================
|
||||
-- 学生状态变更处理测试数据
|
||||
-- 用于测试自动化处理脚本
|
||||
-- ===========================================
|
||||
|
||||
-- 注意:请根据实际情况修改学生ID和学号
|
||||
|
||||
-- 插入测试数据到 xg_student_status_change 表
|
||||
-- 状态:0=未处理,1=已处理
|
||||
|
||||
-- 测试休学处理
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) VALUES (
|
||||
10001, 10001, '20240001', 'XIU_XUE', NOW(),
|
||||
CURDATE(), '学生申请休学', 1, 'manual', 0
|
||||
);
|
||||
|
||||
-- 测试退学处理
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) VALUES (
|
||||
10002, 10002, '20240002', 'TUI_XUE', NOW(),
|
||||
CURDATE(), '学生申请退学', 1, 'manual', 0
|
||||
);
|
||||
|
||||
-- 测试毕业处理
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) VALUES (
|
||||
10003, 10003, '20240003', 'BI_YE', NOW(),
|
||||
CURDATE(), '学生毕业处理', 1, 'manual', 0
|
||||
);
|
||||
|
||||
-- 测试复学处理
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) VALUES (
|
||||
10004, 10004, '20240004', 'FU_XUE', NOW(),
|
||||
CURDATE(), '学生申请复学', 1, 'manual', 0
|
||||
);
|
||||
|
||||
-- 批量测试数据(休学)
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) SELECT
|
||||
20000 + (@row_number := @row_number + 1),
|
||||
20000 + @row_number,
|
||||
CONCAT('2024', LPAD(@row_number, 4, '0')),
|
||||
'XIU_XUE',
|
||||
NOW(),
|
||||
CURDATE(),
|
||||
CONCAT('批量测试休学-', @row_number),
|
||||
1,
|
||||
'manual',
|
||||
0
|
||||
FROM (SELECT @row_number := 0) r
|
||||
CROSS JOIN (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) nums;
|
||||
|
||||
-- 批量测试数据(退学)
|
||||
INSERT INTO xg_student_status_change (
|
||||
id, student_id, student_no, change_type, apply_date,
|
||||
effective_date, reason, operator_id, source, process_status
|
||||
) SELECT
|
||||
30000 + (@row_number2 := @row_number2 + 1),
|
||||
30000 + @row_number2,
|
||||
CONCAT('2024', LPAD(@row_number2 + 10, 4, '0')),
|
||||
'TUI_XUE',
|
||||
NOW(),
|
||||
CURDATE(),
|
||||
CONCAT('批量测试退学-', @row_number2),
|
||||
1,
|
||||
'manual',
|
||||
0
|
||||
FROM (SELECT @row_number2 := 0) r2
|
||||
CROSS JOIN (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) nums2;
|
||||
|
||||
-- 查询测试数据
|
||||
SELECT
|
||||
'测试数据插入完成' as status,
|
||||
COUNT(*) as total_test_records
|
||||
FROM xg_student_status_change
|
||||
WHERE id >= 10001;
|
||||
|
||||
-- 按类型统计
|
||||
SELECT
|
||||
change_type,
|
||||
COUNT(*) as count
|
||||
FROM xg_student_status_change
|
||||
WHERE id >= 10001
|
||||
GROUP BY change_type
|
||||
ORDER BY change_type;
|
||||
|
||||
-- ===========================================
|
||||
-- 清理测试数据的SQL(执行前请确认)
|
||||
-- ===========================================
|
||||
|
||||
-- DELETE FROM xg_student_status_change WHERE id >= 10001;
|
||||
-- COMMIT;
|
||||
Reference in new issue
Block a user