提交 93ff7706 authored 作者: 陈泽健's avatar 陈泽健

Merge remote-tracking branch 'origin/develop' into develop

#!/bin/bash
# ==================== 配置区 ====================
CONTAINER_NAME="umysql"
DB_USER="root"
HOST_BACKUP_DIR="/opt/mysql" # 宿主机备份目录
LOG_FILE="/var/log/backup_mysql_databases.log"
RETENTION_DAYS=30
TARGET_DBS=("devops" "devops_voice" "huazhao2" "nacos_mysql" "offline" "ubains" "wifi" "voice" "ubains_nacos_config" "ubains_sso")
DATE=$(date +"%Y%m%d")
CONTAINER_TMP_DIR="/tmp/mysql_backup_$$.sql.gz" # 容器内临时目录(带PID防冲突)
# ==================== 日志函数 ====================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec "$CONTAINER_NAME" printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
# ==================== 初始化 ====================
mkdir -p "$HOST_BACKUP_DIR/$DATE"
touch "$LOG_FILE"
log "===== 开始备份任务 (容器: $CONTAINER_NAME) ====="
# 在容器内创建临时目录
docker exec "$CONTAINER_NAME" mkdir -p "$CONTAINER_TMP_DIR"
if [ $? -ne 0 ]; then
log "❌ 无法在容器内创建临时目录,请检查容器是否运行。"
exit 1
fi
DB_PASSWORD=$(get_mysql_password)
if [ -z "$DB_PASSWORD" ]; then
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 测试连接
if docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SELECT 1;" >/dev/null 2>&1; then
log "✅ 使用密码成功连接数据库"
else
log "❌ 使用密码连接数据库失败"
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 获取容器中实际存在的数据库列表
EXISTING_DBS_RAW=$(docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SHOW DATABASES;" 2>/dev/null)
mapfile -t EXISTING_DBS <<< "$EXISTING_DBS_RAW"
declare -A DB_EXISTS
for db in "${EXISTING_DBS[@]}"; do
DB_EXISTS["$db"]=1
done
# ==================== 备份每个目标数据库 ====================
SUCCESS_COUNT=0
for db in "${TARGET_DBS[@]}"; do
if [[ -n "${DB_EXISTS[$db]}" ]]; then
CONTAINER_DUMP_FILE="$CONTAINER_TMP_DIR/${db}.sql.gz"
HOST_DUMP_FILE="$HOST_BACKUP_DIR/$DATE/${db}.sql.gz"
log "开始备份数据库: $db"
# 在容器内执行 mysqldump + gzip
docker exec "$CONTAINER_NAME" \
sh -c "mysqldump -u'$DB_USER' -p'$DB_PASSWORD' --single-transaction --routines --triggers --events '$db' | gzip > '$CONTAINER_DUMP_FILE'"
if [ $? -eq 0 ] && docker exec "$CONTAINER_NAME" [ -s "$CONTAINER_DUMP_FILE" ]; then
# 从容器复制到宿主机
docker cp "$CONTAINER_NAME:$CONTAINER_DUMP_FILE" "$HOST_DUMP_FILE"
if [ $? -eq 0 ] && [ -s "$HOST_DUMP_FILE" ]; then
log "✅ 备份成功: $db -> $HOST_DUMP_FILE"
((SUCCESS_COUNT++))
else
log "❌ 复制到宿主机失败: $db"
[ -f "$HOST_DUMP_FILE" ] && rm -f "$HOST_DUMP_FILE"
fi
else
log "❌ 容器内备份失败: $db"
fi
# 立即删除容器内的临时文件(无论成功与否)
docker exec "$CONTAINER_NAME" rm -f "$CONTAINER_DUMP_FILE"
else
log "⚠️ 跳过: 数据库 $db 不存在"
fi
done
# 清理容器内临时目录
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
log "本次共成功备份 $SUCCESS_COUNT 个数据库"
# ==================== 清理超过30天的旧备份 ====================
log "开始清理超过 $RETENTION_DAYS 天的旧备份..."
find "$HOST_BACKUP_DIR" -maxdepth 1 -type d -name "????????" -mtime +$RETENTION_DAYS -exec rm -rf {} + 2>/dev/null
log "===== 备份任务结束 ====="
#!/bin/bash
# clear_deleted_files.sh - 定时清理被进程占用的已删除文件
LOG_FILE="/var/log/cleanup_deleted_files.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] 开始检查被占用的已删除文件..." >> "$LOG_FILE"
# 使用 lsof +L1 查找 link count 为 0(即已删除)但仍被打开的文件
DELETED_ENTRIES=$(lsof +L1 2>/dev/null | grep -v "COMMAND")
if [ -z "$DELETED_ENTRIES" ]; then
echo "[$DATE] 未发现被占用的已删除文件。" >> "$LOG_FILE"
exit 0
fi
echo "[$DATE] 发现以下被占用的已删除文件:" >> "$LOG_FILE"
echo "$DELETED_ENTRIES" >> "$LOG_FILE"
# 提取唯一 PID 列表
PIDS=$(echo "$DELETED_ENTRIES" | awk 'NR>1 {print $2}' | sort -u)
for PID in $PIDS; do
if ! kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] PID $PID 已不存在,跳过。" >> "$LOG_FILE"
continue
fi
CMD=$(ps -p "$PID" -o comm= 2>/dev/null | tr -d ' ')
echo "[$DATE] 处理进程: PID=$PID, CMD=$CMD" >> "$LOG_FILE"
# 尝试发送 SIGHUP(适用于 Nginx、rsyslog 等支持 reload 的服务)
if kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] 向 PID $PID 发送 SIGHUP 信号..." >> "$LOG_FILE"
kill -HUP "$PID" 2>/dev/null && continue
fi
# 若 SIGHUP 无效或不支持,记录警告(不强制 kill,避免服务中断)
echo "[$DATE] WARNING: 无法通过 SIGHUP 释放 PID $PID 的文件句柄。建议手动处理或配置 logrotate。" >> "$LOG_FILE"
done
echo "[$DATE] 检查完成。" >> "$LOG_FILE"
#!/bin/bash
# 宿主机上的脚本:检查 EMQX,如果容器未运行则重启 uemqx 容器
LOG_FILE="/var/log/monitor_emqx_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
check_emqx() {
# 检查 uemqx 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 通过 docker exec 检查 EMQX 进程是否在容器内运行
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
# 检查EMQX是否在运行状态(使用EMQX自带的命令)
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
# 额外验证EMQX是否真正可用
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "EMQX 服务状态正常"
return 0
else
log "警告: emqx_ctl 命令执行成功,但返回意外状态"
return 1
fi
else
log "警告: 容器正在运行,EMQX 进程存在,但 emqx_ctl 命令执行失败"
return 1
fi
else
log "警告: 容器正在运行,但在容器内未找到 EMQX 进程"
return 1
fi
else
log "信息: uemqx 容器未运行"
return 1
fi
}
restart_emqx_container() {
log "EMQX 未运行。正在尝试重启容器 'uemqx'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 停止可能挂起的容器
docker stop uemqx >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uemqx; then
log "成功: EMQX 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 30 秒让 EMQX 服务完全启动..."
for i in {1..30}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
log "信息: EMQX 容器现在正在运行。"
# 再次检查EMQX进程是否已启动
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
log "信息: EMQX 进程在容器内正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "信息: EMQX 服务状态正常。"
return 0
else
log "错误: EMQX 进程运行中,但服务状态异常。"
return 1
fi
else
log "错误: EMQX 进程运行中,但服务状态检查失败。"
return 1
fi
else
log "错误: EMQX 进程在容器内未运行。"
return 1
fi
else
log "错误: EMQX 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 EMQX 容器。"
return 1
fi
else
log "错误: 容器 'uemqx' 不存在!"
log "信息: 您可能需要手动重新创建 EMQX 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 EMQX 服务状态..."
if check_emqx; then
log "EMQX 正在运行且状态正常。"
else
log "EMQX 无响应或容器未运行。"
restart_emqx_container
# 检查重启后是否正常工作
if check_emqx; then
log "EMQX 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 EMQX 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uemqx"
fi
fi
\ No newline at end of file
#!/bin/bash
# 宿主机上的脚本:检查 MySQL,如果容器未运行则重启 umysql 容器
LOG_FILE="/var/log/monitor_mysql_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec umysql printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
check_mysql() {
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
# 尝试连接数据库
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" 2>/dev/null; then
# 尝试执行一个简单的SQL查询来确认数据库功能正常
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "MySQL 服务连接正常,可以执行SQL查询"
return 0
else
log "警告: MySQL 服务可以ping通,但无法执行SQL查询"
return 1
fi
else
log "警告: 无法连接到 MySQL 服务"
return 1
fi
else
log "信息: umysql 容器未运行"
return 1
fi
}
restart_mysql_container() {
log "MySQL 未运行。正在尝试重启容器 'umysql'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "umysql"; then
# 停止可能挂起的容器
docker stop umysql >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start umysql; then
log "成功: MySQL 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 60 秒让 MySQL 服务完全启动..."
for i in {1..60}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
log "信息: MySQL 容器现在正在运行。"
# 等待一段时间后检查服务状态
log "信息: 等待 20 秒后检查服务状态..."
sleep 60
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" >/dev/null 2>&1; then
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "信息: MySQL 服务状态正常。"
return 0
else
log "错误: MySQL 服务运行中,但无法执行SQL查询。"
return 1
fi
else
log "错误: MySQL 服务状态检查失败。"
return 1
fi
else
log "错误: MySQL 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 MySQL 容器。"
return 1
fi
else
log "错误: 容器 'umysql' 不存在!"
log "信息: 您可能需要手动重新创建 MySQL 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 MySQL 服务状态..."
if check_mysql; then
log "MySQL 正在运行且状态正常。"
else
log "MySQL 无响应或容器未运行。"
restart_mysql_container
# 检查重启后是否正常工作
if check_mysql; then
log "MySQL 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 MySQL 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs umysql"
fi
fi
\ No newline at end of file
#!/bin/bash
# 宿主机上的脚本:检查 Nacos,失败则重启 ujava2 容器中的服务
LOG_FILE="/var/log/monitor_nacos_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
check_nacos() {
# 确保 127.0.0.1:8848 可访问(Nacos 端口已映射到宿主机)
if curl -sf http://127.0.0.1:8848/nacos/v1/console/health/readiness >/dev/null; then
return 0
else
return 1
fi
}
restart_in_container() {
log "Nacos NOT READY. Restarting services in container 'ujava2'..."
# 检查容器是否正在运行(精确匹配名称)
if ! docker ps --format '{{.Names}}' | grep -Fxq "ujava2"; then
log "ERROR: Container 'ujava2' is not running!"
return 1
fi
# 在容器内执行 start.sh
if docker exec ujava2 /var/www/java/start.sh; then
log "SUCCESS: Services restarted in ujava2."
else
log "ERROR: Failed to run start.sh in ujava2."
fi
}
# 主逻辑
log "开始检查 Nacos 服务状态..."
if check_nacos; then
log "Nacos is healthy."
else
log "Nacos is not responding."
restart_in_container
fi
\ No newline at end of file
#!/bin/bash
# 宿主机上的脚本:检查 Redis,如果容器未运行则重启 uredis 容器
LOG_FILE="/var/log/monitor_redis_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
# 直接在脚本中定义 Redis 密码
REDIS_PASSWORD="dNrprU&2S"
check_redis() {
# 检查 uredis 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
# 首先尝试不使用密码的 ping 命令
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 无密码情况下能 ping 通
log "Redis 服务状态正常"
return 0
else
# 检查是否是认证问题
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
log "检测到需要认证的 Redis 服务,正在尝试使用密码..."
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "Redis 服务状态正常(已通过密码认证)"
return 0
else
log "警告: 使用密码认证成功,但 ping 返回意外状态: $ping_output"
return 1
fi
else
log "警告: 需要认证,但无法使用预设密码连接到 Redis"
return 1
fi
else
# 不是认证问题,可能是其他错误
log "警告: Redis 连接失败,错误信息: $auth_output"
return 1
fi
fi
else
log "信息: uredis 容器未运行"
return 1
fi
}
restart_redis_container() {
log "Redis 未运行。正在尝试重启容器 'uredis'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uredis"; then
# 停止可能挂起的容器
docker stop uredis >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uredis; then
log "成功: Redis 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 Redis 容器。"
# 尝试清理数据目录并重启
log "信息: 尝试清理数据目录并重新启动 Redis 容器..."
# 检查并删除可能存在的数据目录
if [ -d "/var/www/java/redis/data" ]; then
log "信息: 清理 /var/www/java/redis/data 目录..."
rm -rf /var/www/java/redis/data/*
fi
if [ -d "/var/www/redis/data" ]; then
log "信息: 清理 /var/www/redis/data 目录..."
rm -rf /var/www/redis/data/*
fi
# 再次尝试启动容器
log "信息: 再次尝试启动 Redis 容器..."
if docker start uredis; then
log "成功: Redis 容器在清理数据后已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 即使清理了数据目录,仍然无法启动 Redis 容器。"
return 1
fi
fi
else
log "错误: 容器 'uredis' 不存在!"
log "信息: 您可能需要手动重新创建 Redis 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 Redis 服务状态..."
if check_redis; then
log "Redis 正在运行且状态正常。"
else
log "Redis 无响应或容器未运行。"
restart_redis_container
# 检查重启后是否正常工作
if check_redis; then
log "Redis 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 Redis 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uredis"
fi
fi
\ No newline at end of file
#!/bin/bash
# ==================== 配置区域 ====================
# 可在此处配置要监控的容器名称,默认为ujava2
CONTAINER_NAME="${UJAVA_CONTAINER_NAME:-${1:-ujava2}}"
LOG_FILE="/var/log/monitor_ujava_service.log"
# ==================== 日志函数 ====================
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
check_ujava() {
# 检查指定的 ujava 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
# 获取运行中的Java进程列表
running_processes=$(docker exec "$CONTAINER_NAME" ps aux | grep -E "java.*\.jar|ubains" | grep -v grep)
if [ -n "$running_processes" ]; then
log "检测到容器中有Java进程在运行"
log "运行中的Java进程: $(echo "$running_processes" | wc -l) 个"
# 定义服务目录和JAR文件的对应关系
declare -A service_map
service_map["/var/www/java/auth-sso-auth"]="ubains-auth.jar"
service_map["/var/www/java/auth-sso-gatway"]="ubains-gateway.jar"
service_map["/var/www/java/auth-sso-system"]="ubains-modules-system.jar"
service_map["/var/www/java/api-java-meeting2.0"]="ubains-meeting-inner-api-1.0-SNAPSHOT"
service_map["/var/www/java/external-meeting-api"]="ubains-meeting-api-1.0-SNAPSHOT.jar"
service_map["/var/www/java/api-dubbo-meeting-control"]="ubains-dubbo-meeting-control"
service_map["/var/www/java/api-dubbo-smc-three"]="ubains-dubbo-smc-three-0.0.1"
missing_services=()
active_services=()
# 检查每个服务是否在运行
for dir in "${!service_map[@]}"; do
jar_file="${service_map[$dir]}"
if echo "$running_processes" | grep -q "$jar_file"; then
active_services+=("$jar_file")
else
missing_services+=("$dir:$jar_file")
fi
done
if [ ${#missing_services[@]} -eq 0 ]; then
log "所有预期的Java进程都在运行中 (共 ${#active_services[@]} 个)"
return 0
else
log "警告: 以下服务未运行: ${missing_services[*]}"
log "信息: 以下服务正在运行: ${active_services[*]}"
return 1
fi
else
log "警告: 容器运行中,但未检测到Java进程"
# 返回1表示服务不正常
return 1
fi
else
log "信息: 容器 $CONTAINER_NAME 未运行"
return 1
fi
}
restart_missing_services() {
log "检测到服务缺失,正在尝试启动缺失的服务..."
# 定义服务目录和JAR文件的对应关系
declare -A service_map
service_map["/var/www/java/auth-sso-auth"]="ubains-auth.jar"
service_map["/var/www/java/auth-sso-gatway"]="ubains-gateway.jar"
service_map["/var/www/java/auth-sso-system"]="ubains-modules-system.jar"
service_map["/var/www/java/api-java-meeting2.0"]="ubains-meeting-inner-api-1.0-SNAPSHOT"
service_map["/var/www/java/external-meeting-api"]="ubains-meeting-api-1.0-SNAPSHOT.jar"
service_map["/var/www/java/api-dubbo-meeting-control"]="ubains-dubbo-meeting-control"
service_map["/var/www/java/api-dubbo-smc-three"]="ubains-dubbo-smc-three-0.0.1"
# 统计启动了多少服务
started_count=0
# 遍历每个服务,检查是否运行,如果没有则启动
for dir in "${!service_map[@]}"; do
jar_file="${service_map[$dir]}"
# 检查服务是否已经运行
running_processes=$(docker exec "$CONTAINER_NAME" ps aux | grep -E "java.*\.jar|ubains" | grep -v grep)
if ! echo "$running_processes" | grep -q "$jar_file"; then
log "启动服务: $jar_file 在目录 $dir"
# 检查JAR文件是否存在
if docker exec -w "$dir" "$CONTAINER_NAME" test -f "$jar_file\.jar"; then
# 直接执行Java命令启动服务,而不是运行run.sh
docker exec -d -w "$dir" "$CONTAINER_NAME" sh -c "nohup java -Xms1024m -Xmx1024m -jar -DAPP_CONFIG=./config $jar_file\.jar > log.out 2>&1 &"
log "已尝试启动 $jar_file"
((started_count++))
elif docker exec -w "$dir" "$CONTAINER_NAME" test -f "$jar_file-0.0.1-SNAPSHOT\.jar"; then
# 对于带版本号的JAR文件
docker exec -d -w "$dir" "$CONTAINER_NAME" sh -c "nohup java -Xms1024m -Xmx1024m -jar -DAPP_CONFIG=./config $jar_file-0.0.1-SNAPSHOT\.jar > log.out 2>&1 &"
log "已尝试启动 $jar_file-0.0.1-SNAPSHOT.jar"
((started_count++))
elif docker exec -w "$dir" "$CONTAINER_NAME" test -f "run.sh"; then
# 如果JAR文件不存在但run.sh存在,安全地执行run.sh(传递参数以避免默认执行start)
docker exec -d -w "$dir" "$CONTAINER_NAME" sh -c "./run.sh start"
log "已尝试使用run.sh启动 $jar_file"
((started_count++))
else
log "错误: JAR文件和run.sh脚本在 $dir 目录中都不存在"
fi
else
log "服务 $jar_file 已经在运行"
fi
done
if [ $started_count -gt 0 ]; then
log "成功启动了 $started_count 个服务,等待服务启动..."
return 0
else
log "没有需要启动的服务"
return 0
fi
}
wait_for_services_to_start() {
log "开始监控服务启动状态,最多等待10分钟..."
# 循环检查服务是否启动成功,最多等待10次,每次等待1分钟
for i in {1..10}; do
log "等待第 $i 分钟,检查服务是否已启动..."
# 检查是否还有缺失的服务
running_processes=$(docker exec "$CONTAINER_NAME" ps aux | grep -E "java.*\.jar|ubains" | grep -v grep)
missing_services=()
# 定义服务目录和JAR文件的对应关系
declare -A service_map
service_map["/var/www/java/auth-sso-auth"]="ubains-auth.jar"
service_map["/var/www/java/auth-sso-gatway"]="ubains-gateway.jar"
service_map["/var/www/java/auth-sso-system"]="ubains-modules-system.jar"
service_map["/var/www/java/api-java-meeting2.0"]="ubains-meeting-inner-api-1.0-SNAPSHOT"
service_map["/var/www/java/external-meeting-api"]="ubains-meeting-api-1.0-SNAPSHOT.jar"
service_map["/var/www/java/api-dubbo-meeting-control"]="ubains-dubbo-meeting-control"
service_map["/var/www/java/api-dubbo-smc-three"]="ubains-dubbo-smc-three-0.0.1"
# 检查每个服务是否在运行
for dir in "${!service_map[@]}"; do
jar_file="${service_map[$dir]}"
if ! echo "$running_processes" | grep -q "$jar_file"; then
missing_services+=("$dir:$jar_file")
fi
done
if [ ${#missing_services[@]} -eq 0 ]; then
log "恭喜!所有服务都已成功启动。"
return 0
else
log "仍有 ${#missing_services[@]} 个服务未启动: ${missing_services[*]}"
fi
# 等待1分钟
sleep 60
done
log "已等待10分钟,仍有服务未能启动,将重启整个容器。"
return 1
}
restart_ujava_container() {
log "容器 $CONTAINER_NAME 服务不正常。正在尝试重启容器 '$CONTAINER_NAME'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
# 停止可能挂起的容器
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start "$CONTAINER_NAME"; then
log "成功: 容器 $CONTAINER_NAME 已成功启动。"
# 等待几分钟让Java服务启动
log "信息: 等待 90 秒让 Java 服务完全启动..."
for i in {1..90}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
log "信息: 容器 $CONTAINER_NAME 现在正在运行。"
# 启动缺失的服务
restart_missing_services
# 检查Java进程是否已启动
log "信息: 检查服务状态..."
if check_ujava; then
log "信息: 容器 $CONTAINER_NAME 服务状态正常。"
return 0
else
log "错误: 容器 $CONTAINER_NAME 进程运行中,但服务状态异常。"
return 1
fi
else
log "错误: 容器 $CONTAINER_NAME 在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动容器 $CONTAINER_NAME。"
return 1
fi
else
log "错误: 容器 '$CONTAINER_NAME' 不存在!"
log "信息: 您可能需要手动重新创建 $CONTAINER_NAME 容器。"
return 1
fi
}
# 主逻辑
log "开始检查容器 $CONTAINER_NAME 服务状态..."
if check_ujava; then
log "容器 $CONTAINER_NAME 正在运行且状态正常。"
else
log "容器 $CONTAINER_NAME 服务不完整或容器未运行。"
# 如果容器在运行但服务不完整,尝试启动缺失的服务
if docker ps --format '{{.Names}}' | grep -Fxq "$CONTAINER_NAME"; then
# 先获取当前运行的服务状态
running_processes=$(docker exec "$CONTAINER_NAME" ps aux | grep -E "java.*\.jar|ubains" | grep -v grep)
# 如果没有任何Java进程在运行,可能是所有服务都崩溃了,直接重启容器
if [ -z "$running_processes" ]; then
log "警告: 检测到没有任何Java进程在运行,尝试重启整个容器。"
restart_ujava_container
else
# 否则,尝试启动缺失的服务
restart_missing_services
# 检查重启后是否正常工作
if check_ujava; then
log "容器 $CONTAINER_NAME 服务已恢复,现在状态正常。"
else
log "容器 $CONTAINER_NAME 服务仍然不正常,尝试重启整个容器。"
restart_ujava_container
fi
fi
else
# 如果容器不在运行,直接重启容器
restart_ujava_container
fi
# 最终检查
if check_ujava; then
log "容器 $CONTAINER_NAME 已成功恢复,现在状态正常。"
else
log "错误: 尝试恢复后 $CONTAINER_NAME 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs $CONTAINER_NAME"
fi
fi
\ No newline at end of file
#!/bin/bash
# ==================== 配置区 ====================
CONTAINER_NAME="umysql"
DB_USER="root"
HOST_BACKUP_DIR="/opt/mysql" # 宿主机备份目录
LOG_FILE="/var/log/backup_mysql_databases.log"
RETENTION_DAYS=30
TARGET_DBS=("devops" "devops_voice" "huazhao2" "nacos_mysql" "offline" "ubains" "wifi" "voice" "ubains_nacos_config" "ubains_sso")
DATE=$(date +"%Y%m%d")
CONTAINER_TMP_DIR="/tmp/mysql_backup_$$.sql.gz" # 容器内临时目录(带PID防冲突)
# ==================== 日志函数 ====================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec "$CONTAINER_NAME" printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
# ==================== 初始化 ====================
mkdir -p "$HOST_BACKUP_DIR/$DATE"
touch "$LOG_FILE"
log "===== 开始备份任务 (容器: $CONTAINER_NAME) ====="
# 在容器内创建临时目录
docker exec "$CONTAINER_NAME" mkdir -p "$CONTAINER_TMP_DIR"
if [ $? -ne 0 ]; then
log "❌ 无法在容器内创建临时目录,请检查容器是否运行。"
exit 1
fi
DB_PASSWORD=$(get_mysql_password)
if [ -z "$DB_PASSWORD" ]; then
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 测试连接
if docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SELECT 1;" >/dev/null 2>&1; then
log "✅ 使用密码成功连接数据库"
else
log "❌ 使用密码连接数据库失败"
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 获取容器中实际存在的数据库列表
EXISTING_DBS_RAW=$(docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SHOW DATABASES;" 2>/dev/null)
mapfile -t EXISTING_DBS <<< "$EXISTING_DBS_RAW"
declare -A DB_EXISTS
for db in "${EXISTING_DBS[@]}"; do
DB_EXISTS["$db"]=1
done
# ==================== 备份每个目标数据库 ====================
SUCCESS_COUNT=0
for db in "${TARGET_DBS[@]}"; do
if [[ -n "${DB_EXISTS[$db]}" ]]; then
CONTAINER_DUMP_FILE="$CONTAINER_TMP_DIR/${db}.sql.gz"
HOST_DUMP_FILE="$HOST_BACKUP_DIR/$DATE/${db}.sql.gz"
log "开始备份数据库: $db"
# 在容器内执行 mysqldump + gzip
docker exec "$CONTAINER_NAME" \
sh -c "mysqldump -u'$DB_USER' -p'$DB_PASSWORD' --single-transaction --routines --triggers --events '$db' | gzip > '$CONTAINER_DUMP_FILE'"
if [ $? -eq 0 ] && docker exec "$CONTAINER_NAME" [ -s "$CONTAINER_DUMP_FILE" ]; then
# 从容器复制到宿主机
docker cp "$CONTAINER_NAME:$CONTAINER_DUMP_FILE" "$HOST_DUMP_FILE"
if [ $? -eq 0 ] && [ -s "$HOST_DUMP_FILE" ]; then
log "✅ 备份成功: $db -> $HOST_DUMP_FILE"
((SUCCESS_COUNT++))
else
log "❌ 复制到宿主机失败: $db"
[ -f "$HOST_DUMP_FILE" ] && rm -f "$HOST_DUMP_FILE"
fi
else
log "❌ 容器内备份失败: $db"
fi
# 立即删除容器内的临时文件(无论成功与否)
docker exec "$CONTAINER_NAME" rm -f "$CONTAINER_DUMP_FILE"
else
log "⚠️ 跳过: 数据库 $db 不存在"
fi
done
# 清理容器内临时目录
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
log "本次共成功备份 $SUCCESS_COUNT 个数据库"
# ==================== 清理超过30天的旧备份 ====================
log "开始清理超过 $RETENTION_DAYS 天的旧备份..."
find "$HOST_BACKUP_DIR" -maxdepth 1 -type d -name "????????" -mtime +$RETENTION_DAYS -exec rm -rf {} + 2>/dev/null
log "===== 备份任务结束 ====="
#!/bin/bash
# clear_deleted_files.sh - 定时清理被进程占用的已删除文件
LOG_FILE="/var/log/cleanup_deleted_files.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] 开始检查被占用的已删除文件..." >> "$LOG_FILE"
# 使用 lsof +L1 查找 link count 为 0(即已删除)但仍被打开的文件
DELETED_ENTRIES=$(lsof +L1 2>/dev/null | grep -v "COMMAND")
if [ -z "$DELETED_ENTRIES" ]; then
echo "[$DATE] 未发现被占用的已删除文件。" >> "$LOG_FILE"
exit 0
fi
echo "[$DATE] 发现以下被占用的已删除文件:" >> "$LOG_FILE"
echo "$DELETED_ENTRIES" >> "$LOG_FILE"
# 提取唯一 PID 列表
PIDS=$(echo "$DELETED_ENTRIES" | awk 'NR>1 {print $2}' | sort -u)
for PID in $PIDS; do
if ! kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] PID $PID 已不存在,跳过。" >> "$LOG_FILE"
continue
fi
CMD=$(ps -p "$PID" -o comm= 2>/dev/null | tr -d ' ')
echo "[$DATE] 处理进程: PID=$PID, CMD=$CMD" >> "$LOG_FILE"
# 尝试发送 SIGHUP(适用于 Nginx、rsyslog 等支持 reload 的服务)
if kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] 向 PID $PID 发送 SIGHUP 信号..." >> "$LOG_FILE"
kill -HUP "$PID" 2>/dev/null && continue
fi
# 若 SIGHUP 无效或不支持,记录警告(不强制 kill,避免服务中断)
echo "[$DATE] WARNING: 无法通过 SIGHUP 释放 PID $PID 的文件句柄。建议手动处理或配置 logrotate。" >> "$LOG_FILE"
done
echo "[$DATE] 检查完成。" >> "$LOG_FILE"
#!/bin/bash
# 宿主机上的脚本:检查 EMQX,如果容器未运行则重启 uemqx 容器
LOG_FILE="/var/log/monitor_emqx_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
check_emqx() {
# 检查 uemqx 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 通过 docker exec 检查 EMQX 进程是否在容器内运行
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
# 检查EMQX是否在运行状态(使用EMQX自带的命令)
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
# 额外验证EMQX是否真正可用
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "EMQX 服务状态正常"
return 0
else
log "警告: emqx_ctl 命令执行成功,但返回意外状态"
return 1
fi
else
log "警告: 容器正在运行,EMQX 进程存在,但 emqx_ctl 命令执行失败"
return 1
fi
else
log "警告: 容器正在运行,但在容器内未找到 EMQX 进程"
return 1
fi
else
log "信息: uemqx 容器未运行"
return 1
fi
}
restart_emqx_container() {
log "EMQX 未运行。正在尝试重启容器 'uemqx'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 停止可能挂起的容器
docker stop uemqx >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uemqx; then
log "成功: EMQX 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 30 秒让 EMQX 服务完全启动..."
for i in {1..30}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
log "信息: EMQX 容器现在正在运行。"
# 再次检查EMQX进程是否已启动
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
log "信息: EMQX 进程在容器内正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "信息: EMQX 服务状态正常。"
return 0
else
log "错误: EMQX 进程运行中,但服务状态异常。"
return 1
fi
else
log "错误: EMQX 进程运行中,但服务状态检查失败。"
return 1
fi
else
log "错误: EMQX 进程在容器内未运行。"
return 1
fi
else
log "错误: EMQX 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 EMQX 容器。"
return 1
fi
else
log "错误: 容器 'uemqx' 不存在!"
log "信息: 您可能需要手动重新创建 EMQX 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 EMQX 服务状态..."
if check_emqx; then
log "EMQX 正在运行且状态正常。"
else
log "EMQX 无响应或容器未运行。"
restart_emqx_container
# 检查重启后是否正常工作
if check_emqx; then
log "EMQX 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 EMQX 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uemqx"
fi
fi
\ No newline at end of file
#!/bin/bash
# --- 配置区域 ---
# 日志文件路径
LOG_FILE="/var/log/monitor_external_api_services.log"
# 定义要监控的服务及其相关信息
# 格式: "进程名:目录路径:启动脚本路径"
SERVICES=(
"ubains-meeting-api-1.0-SNAPSHOT.jar:/var/www/java/external-meeting-api:/var/www/java/external-meeting-api/run.sh"
"malan:/var/www/malan:/var/www/malan/run.sh"
)
# --- 函数定义 ---
# 记录日志的函数
log_message() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}
# 检查进程是否运行
is_process_running() {
local process_name="$1"
# 使用 pgrep -f 搜索命令行中包含该名称的进程
# 对于 .jar 文件,通常搜索的是 java -jar ...<jar_name>
# 对于其他程序,搜索其进程名
if [[ "$process_name" == *.jar ]]; then
# 如果是 JAR 文件,搜索 java 进程中包含该 jar 名称的
pgrep -f "java.*$process_name" > /dev/null
else
# 否则直接搜索进程名
pgrep -x "$process_name" > /dev/null
fi
if [ $? -eq 0 ]; then
return 0 # 进程运行中
else
return 1 # 进程未运行
fi
}
# 检查目录是否存在
is_directory_exists() {
local dir_path="$1"
[ -d "$dir_path" ]
}
# 检查启动脚本是否存在且可执行
is_script_executable() {
local script_path="$1"
[ -x "$script_path" ]
}
# 启动服务
start_service() {
local service_name="$1"
local dir_path="$2"
local script_path="$3"
log_message "尝试启动服务 '$service_name'..."
# 切换到服务目录并执行启动脚本
# 使用子shell (cd ...) 以确保不影响当前脚本的工作目录
(
cd "$dir_path" || { log_message "错误: 无法切换到目录 '$dir_path'"; return 1; }
# 检查启动脚本是否存在且可执行
if ! is_script_executable "$script_path"; then
log_message "错误: 启动脚本 '$script_path' 不存在或不可执行。"
return 1
fi
# 执行启动脚本
# 使用 nohup 将进程与终端脱离,使其在后台持续运行
# 输出重定向到 startup.log 或 /dev/null
nohup "./$(basename "$script_path")" > startup.log 2>&1 &
# 等待一小段时间,让进程有机会启动
sleep 3
# 再次检查进程是否启动成功
if is_process_running "$service_name"; then
log_message "服务 '$service_name' 启动成功。"
return 0
else
log_message "错误: 服务 '$service_name' 启动失败。"
return 1
fi
)
}
# --- 主逻辑 ---
# 初始化日志
log_message "=== 服务监控脚本开始执行 ==="
# 遍历所有服务
for service_info in "${SERVICES[@]}"; do
# 解析服务信息
IFS=':' read -r service_name dir_path script_path <<< "$service_info"
# 去除可能的前后空格
service_name=$(echo "$service_name" | xargs)
dir_path=$(echo "$dir_path" | xargs)
script_path=$(echo "$script_path" | xargs)
log_message "检查服务: $service_name (目录: $dir_path, 启动脚本: $script_path)"
# 检查目录是否存在
if ! is_directory_exists "$dir_path"; then
log_message "跳过服务 '$service_name': 目录 '$dir_path' 不存在。"
continue # 跳过当前循环,检查下一个服务
fi
# 检查进程是否运行
if is_process_running "$service_name"; then
log_message "服务 '$service_name' 正在运行。"
else
log_message "服务 '$service_name' 未运行。"
# 尝试启动服务
start_service "$service_name" "$dir_path" "$script_path"
fi
done
log_message "=== 服务监控脚本执行完毕 ==="
#!/bin/bash
# 宿主机上的脚本:检查 MySQL,如果容器未运行则重启 umysql 容器
LOG_FILE="/var/log/monitor_mysql_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec umysql printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
check_mysql() {
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
# 尝试连接数据库
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" 2>/dev/null; then
# 尝试执行一个简单的SQL查询来确认数据库功能正常
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "MySQL 服务连接正常,可以执行SQL查询"
return 0
else
log "警告: MySQL 服务可以ping通,但无法执行SQL查询"
return 1
fi
else
log "警告: 无法连接到 MySQL 服务"
return 1
fi
else
log "信息: umysql 容器未运行"
return 1
fi
}
restart_mysql_container() {
log "MySQL 未运行。正在尝试重启容器 'umysql'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "umysql"; then
# 停止可能挂起的容器
docker stop umysql >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start umysql; then
log "成功: MySQL 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 60 秒让 MySQL 服务完全启动..."
for i in {1..60}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
log "信息: MySQL 容器现在正在运行。"
# 等待一段时间后检查服务状态
log "信息: 等待 20 秒后检查服务状态..."
sleep 20
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" >/dev/null 2>&1; then
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "信息: MySQL 服务状态正常。"
return 0
else
log "错误: MySQL 服务运行中,但无法执行SQL查询。"
return 1
fi
else
log "错误: MySQL 服务状态检查失败。"
return 1
fi
else
log "错误: MySQL 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 MySQL 容器。"
return 1
fi
else
log "错误: 容器 'umysql' 不存在!"
log "信息: 您可能需要手动重新创建 MySQL 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 MySQL 服务状态..."
if check_mysql; then
log "MySQL 正在运行且状态正常。"
else
log "MySQL 无响应或容器未运行。"
restart_mysql_container
# 检查重启后是否正常工作
if check_mysql; then
log "MySQL 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 MySQL 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs umysql"
fi
fi
\ No newline at end of file
#!/bin/bash
# 宿主机上的脚本:检查 Redis,如果容器未运行则重启 uredis 容器
LOG_FILE="/var/log/monitor_redis_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
# 直接在脚本中定义 Redis 密码
REDIS_PASSWORD="dNrprU&2S"
check_redis() {
# 检查 uredis 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
# 首先尝试不使用密码的 ping 命令
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 无密码情况下能 ping 通
log "Redis 服务状态正常"
return 0
else
# 检查是否是认证问题
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
log "检测到需要认证的 Redis 服务,正在尝试使用密码..."
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "Redis 服务状态正常(已通过密码认证)"
return 0
else
log "警告: 使用密码认证成功,但 ping 返回意外状态: $ping_output"
return 1
fi
else
log "警告: 需要认证,但无法使用预设密码连接到 Redis"
return 1
fi
else
# 不是认证问题,可能是其他错误
log "警告: Redis 连接失败,错误信息: $auth_output"
return 1
fi
fi
else
log "信息: uredis 容器未运行"
return 1
fi
}
restart_redis_container() {
log "Redis 未运行。正在尝试重启容器 'uredis'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uredis"; then
# 停止可能挂起的容器
docker stop uredis >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uredis; then
log "成功: Redis 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 Redis 容器。"
# 尝试清理数据目录并重启
log "信息: 尝试清理数据目录并重新启动 Redis 容器..."
# 检查并删除可能存在的数据目录
if [ -d "/var/www/java/redis/data" ]; then
log "信息: 清理 /var/www/java/redis/data 目录..."
rm -rf /var/www/java/redis/data/*
fi
if [ -d "/var/www/redis/data" ]; then
log "信息: 清理 /var/www/redis/data 目录..."
rm -rf /var/www/redis/data/*
fi
# 再次尝试启动容器
log "信息: 再次尝试启动 Redis 容器..."
if docker start uredis; then
log "成功: Redis 容器在清理数据后已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 即使清理了数据目录,仍然无法启动 Redis 容器。"
return 1
fi
fi
else
log "错误: 容器 'uredis' 不存在!"
log "信息: 您可能需要手动重新创建 Redis 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 Redis 服务状态..."
if check_redis; then
log "Redis 正在运行且状态正常。"
else
log "Redis 无响应或容器未运行。"
restart_redis_container
# 检查重启后是否正常工作
if check_redis; then
log "Redis 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 Redis 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uredis"
fi
fi
\ No newline at end of file
#!/bin/bash
#####################################
#用于数据库定时备份 2022-12-12
#####################################
sudo chmod +x /usr/local/docker/UbainsmysqlBakUp.sh
/usr/local/docker/UbainsmysqlBakUp.sh
userset="root"
sleep 5
# 每天下午一点执行脚本
if cat /var/spool/cron/$userset |grep "UbainsmysqlBakUp.sh">/dev/null
then
echo -e "\033[32m
*********************
*已配置数据库定时备份
*
*********************
\033[0m"
sudo service crond restart
else
#每天13点备份
sudo cat >> /var/spool/cron/$userset<<EOF
0 13 * * * bash /usr/local/docker/UbainsmysqlBakUp.sh
EOF
sleep 3
sudo service crond restart
fi
#!/bin/bash
#####################################
#用于数据库备份 23-01-13
#####################################
#预定数据库备份
function ubainsbak()
{
echo -e "\033[33m 检查mysql...... \033[0m"
sudo docker images |grep mysql
sudo docker ps |grep umysql
if [ $? -eq 0 ]; then
sudo docker exec -i umysql bash <<'EOF'
find /home/mysql/ubains/* -mtime +30 -exec rm -rf {} \;
mkdir -p /home/mysql/ubains/$(date +%Y%m%d)
# 备份指定数据库
mysqldump -uroot -p"dNrprU&2S" ubains > /home/mysql/ubains/$(date +%Y%m%d)/ubains_$(date +%Y%m%d_%H%M%S).sql
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
rm /home/mysql/ubains/$log3* -rf
exit
EOF
sudo mkdir -p /opt/mysql/ubains/$(date +%Y%m%d)
sudo docker cp umysql:/home/mysql/ubains/$(date +%Y%m%d) /opt/mysql/ubains
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
sudo rm /opt/mysql/ubains/$log3* -rf
else
echo -e "\033[33m 请正确安装数据库...... \033[0m"
fi
}
#运维数据库备份
function devopsbak()
{
echo -e "\033[33m 检查mysql...... \033[0m"
sudo docker images |grep mysql
sudo docker ps |grep umysql
if [ $? -eq 0 ]; then
sudo docker exec -i umysql bash <<'EOF'
find /home/mysql/devops/* -mtime +30 -exec rm -rf {} \;
mkdir -p /home/mysql/devops/$(date +%Y%m%d)
# 备份指定数据库
mysqldump -uroot -p"dNrprU&2S" devops > /home/mysql/devops/$(date +%Y%m%d)/devops_$(date +%Y%m%d_%H%M%S).sql
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
rm /home/mysql/devops/$log3* -rf
exit
EOF
sudo mkdir -p /opt/mysql/devops/$(date +%Y%m%d)
sudo docker cp umysql:/home/mysql/devops/$(date +%Y%m%d) /opt/mysql/devops
#删除30天之前的备份
log3=$(date -d "30 day ago" +%Y%m%d)
sudo rm /opt/mysql/devops/$log3* -rf
else
echo -e "\033[33m 请正确安装数据库...... \033[0m"
fi
}
#############################################################脚本配置项##################################################################################################
#################预定系统 数据库本地备份###############################
ubainsbak
#################运维系统 数据库本地备份###############################
#devopsbak
...@@ -557,32 +557,6 @@ do ...@@ -557,32 +557,6 @@ do
done done
log "INFO" "数据库密码修改成功!" log "INFO" "数据库密码修改成功!"
log "INFO" "准备处理数据库备份脚本"
$sudoset cp -rf $PWD/UbainsmysqlBakUp.sh /usr/local/docker/
#定时备份数据库
sudo chmod +x /usr/local/docker/UbainsmysqlBakUp.sh
/usr/local/docker/UbainsmysqlBakUp.sh
userset="root"
sleep 5
# 每天下午一点执行脚本
log "INFO" "用cat检测是否有定时任务,没有则准备创建"
if cat /var/spool/cron/$userset |grep "UbainsmysqlBakUp.sh">/dev/null
then
log "INFO" "已配置数据库定时备份,准备重启定时任务"
sudo service crond restart
else
#每天13点备份
log "INFO" "配置数据库定时备份"
sudo tee -a /var/spool/cron/$userset <<EOF
0 13 * * * bash /usr/local/docker/UbainsmysqlBakUp.sh
EOF
sleep 3
#该命令通用centos7、uos
log "INFO" "配置数据库定时备份成功"
sudo service crond restart
log "INFO" "重启定时任务成功"
fi
} }
#x86架构安装mqtt(预定2.0) #x86架构安装mqtt(预定2.0)
...@@ -684,7 +658,7 @@ fi ...@@ -684,7 +658,7 @@ fi
function ntp_uos() { function ntp_uos() {
# 判断如果是centos7就退出安装 # 判断如果是centos7就退出安装
if [ -f /etc/redhat-release ]; then if [ -f /etc/redhat-release ]; then
log "ERROR" "当前系统已经安装NTP服务,无需安装chrony服务" log "ERROR" "当前系统已经安装NTP服务"
return 1 return 1
fi fi
...@@ -908,6 +882,7 @@ function getLatestVersion() { ...@@ -908,6 +882,7 @@ function getLatestVersion() {
#------------------------------服务安装-end------------------------------------------------------------------------------------------------------------------------ #------------------------------服务安装-end------------------------------------------------------------------------------------------------------------------------
#------------------------------文件上传&更改ip-start------------------------------------------------------------------------------------------------------------------------ #------------------------------文件上传&更改ip-start------------------------------------------------------------------------------------------------------------------------
#todo:针对更新对外包,如果存在,需要判断是否更新 #todo:针对更新对外包,如果存在,需要判断是否更新
#-----------------------------------预定系统-------------------------------------------- #-----------------------------------预定系统--------------------------------------------
...@@ -1050,6 +1025,74 @@ sleep 3 ...@@ -1050,6 +1025,74 @@ sleep 3
#------------------------------文件上传&更改ip-end-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------文件上传&更改ip-end--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function check_crontab() {
log "INFO" "开始配置数据库备份、删除进程检测、对外服务检测的定时任务.."
$sudoset mkdir -p /opt/scripts/
# 从定时脚本目录复制脚本到 /opt/scripts/
$sudoset cp -rf $auto_java/scripts/* /opt/scripts/
$sudoset chmod 755 /opt/scripts/*.sh
# 添加定时脚本目录中的脚本定时任务
# 监控 Redis 服务 - 每5分钟检查一次
if ! crontab -l 2>/dev/null | grep -q "monitor_redis_service.sh"; then
log "INFO" "创建监控Redis服务的定时任务..."
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/scripts/monitor_redis_service.sh >> /var/log/monitor_redis_service.log 2>&1") | crontab -
else
log "INFO" "监控Redis服务的定时任务已存在"
fi
# 监控 EMQX 服务 - 每5分钟检查一次
if ! crontab -l 2>/dev/null | grep -q "monitor_emqx_service.sh"; then
log "INFO" "创建监控EMQX服务的定时任务..."
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/scripts/monitor_emqx_service.sh >> /var/log/monitor_emqx_service.log 2>&1") | crontab -
else
log "INFO" "监控EMQX服务的定时任务已存在"
fi
# 监控 MySQL 服务 - 每5分钟检查一次
if ! crontab -l 2>/dev/null | grep -q "monitor_mysql_service.sh"; then
log "INFO" "创建监控MySQL服务的定时任务..."
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/scripts/monitor_mysql_service.sh >> /var/log/monitor_mysql_service.log 2>&1") | crontab -
else
log "INFO" "监控MySQL服务的定时任务已存在"
fi
# 监控外部API服务 - 每5分钟检查一次
if ! crontab -l 2>/dev/null | grep -q "monitor_external_api_services.sh"; then
log "INFO" "创建监控外部API服务的定时任务..."
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/scripts/monitor_external_api_services.sh >> /var/log/monitor_external_api_services.log 2>&1") | crontab -
else
log "INFO" "监控外部API服务的定时任务已存在"
fi
# 数据库备份 - 每天凌晨2点执行
if ! crontab -l 2>/dev/null | grep -q "backup_mysql_databases.sh"; then
log "INFO" "创建数据库备份定时任务..."
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/scripts/backup_mysql_databases.sh >> /var/log/backup_mysql_databases.log 2>&1") | crontab -
else
log "INFO" "数据库备份定时任务已存在"
fi
# 清理已删除文件 - 每天凌晨1点执行
if ! crontab -l 2>/dev/null | grep -q "cleanup_deleted_files.sh"; then
log "INFO" "创建清理已删除文件定时任务..."
(crontab -l 2>/dev/null; echo "0 1 * * * /opt/scripts/cleanup_deleted_files.sh >> /var/log/cleanup_deleted_files.log 2>&1") | crontab -
else
log "INFO" "清理已删除文件定时任务已存在"
fi
# 重启cron服务
sleep 3
if command -v systemctl >/dev/null 2>&1; then
sudo systemctl restart cron 2>/dev/null || sudo systemctl restart crond 2>/dev/null
else
sudo service cron restart 2>/dev/null || sudo service crond restart 2>/dev/null
fi
log "INFO" "定时任务配置成功"
}
#------------------------------全局配置-start-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #------------------------------全局配置-start--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
###服务器检测配置项 ###服务器检测配置项
#mem-check #mem-check
......
#!/bin/bash
# ==================== 配置区 ====================
CONTAINER_NAME="umysql"
DB_USER="root"
HOST_BACKUP_DIR="/opt/mysql" # 宿主机备份目录
LOG_FILE="/var/log/backup_mysql_databases.log"
RETENTION_DAYS=30
TARGET_DBS=("devops" "devops_voice" "huazhao2" "nacos_mysql" "offline" "ubains" "wifi" "voice" "ubains_nacos_config" "ubains_sso")
DATE=$(date +"%Y%m%d")
CONTAINER_TMP_DIR="/tmp/mysql_backup_$$.sql.gz" # 容器内临时目录(带PID防冲突)
# ==================== 日志函数 ====================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec "$CONTAINER_NAME" printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
# ==================== 初始化 ====================
mkdir -p "$HOST_BACKUP_DIR/$DATE"
touch "$LOG_FILE"
log "===== 开始备份任务 (容器: $CONTAINER_NAME) ====="
# 在容器内创建临时目录
docker exec "$CONTAINER_NAME" mkdir -p "$CONTAINER_TMP_DIR"
if [ $? -ne 0 ]; then
log "❌ 无法在容器内创建临时目录,请检查容器是否运行。"
exit 1
fi
DB_PASSWORD=$(get_mysql_password)
if [ -z "$DB_PASSWORD" ]; then
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 测试连接
if docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SELECT 1;" >/dev/null 2>&1; then
log "✅ 使用密码成功连接数据库"
else
log "❌ 使用密码连接数据库失败"
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
exit 1
fi
# 获取容器中实际存在的数据库列表
EXISTING_DBS_RAW=$(docker exec "$CONTAINER_NAME" mysql -u"$DB_USER" -p"$DB_PASSWORD" -Nse "SHOW DATABASES;" 2>/dev/null)
mapfile -t EXISTING_DBS <<< "$EXISTING_DBS_RAW"
declare -A DB_EXISTS
for db in "${EXISTING_DBS[@]}"; do
DB_EXISTS["$db"]=1
done
# ==================== 备份每个目标数据库 ====================
SUCCESS_COUNT=0
for db in "${TARGET_DBS[@]}"; do
if [[ -n "${DB_EXISTS[$db]}" ]]; then
CONTAINER_DUMP_FILE="$CONTAINER_TMP_DIR/${db}.sql.gz"
HOST_DUMP_FILE="$HOST_BACKUP_DIR/$DATE/${db}.sql.gz"
log "开始备份数据库: $db"
# 在容器内执行 mysqldump + gzip
docker exec "$CONTAINER_NAME" \
sh -c "mysqldump -u'$DB_USER' -p'$DB_PASSWORD' --single-transaction --routines --triggers --events '$db' | gzip > '$CONTAINER_DUMP_FILE'"
if [ $? -eq 0 ] && docker exec "$CONTAINER_NAME" [ -s "$CONTAINER_DUMP_FILE" ]; then
# 从容器复制到宿主机
docker cp "$CONTAINER_NAME:$CONTAINER_DUMP_FILE" "$HOST_DUMP_FILE"
if [ $? -eq 0 ] && [ -s "$HOST_DUMP_FILE" ]; then
log "✅ 备份成功: $db -> $HOST_DUMP_FILE"
((SUCCESS_COUNT++))
else
log "❌ 复制到宿主机失败: $db"
[ -f "$HOST_DUMP_FILE" ] && rm -f "$HOST_DUMP_FILE"
fi
else
log "❌ 容器内备份失败: $db"
fi
# 立即删除容器内的临时文件(无论成功与否)
docker exec "$CONTAINER_NAME" rm -f "$CONTAINER_DUMP_FILE"
else
log "⚠️ 跳过: 数据库 $db 不存在"
fi
done
# 清理容器内临时目录
docker exec "$CONTAINER_NAME" rm -rf "$CONTAINER_TMP_DIR"
log "本次共成功备份 $SUCCESS_COUNT 个数据库"
# ==================== 清理超过30天的旧备份 ====================
log "开始清理超过 $RETENTION_DAYS 天的旧备份..."
find "$HOST_BACKUP_DIR" -maxdepth 1 -type d -name "????????" -mtime +$RETENTION_DAYS -exec rm -rf {} + 2>/dev/null
log "===== 备份任务结束 ====="
#!/bin/bash
# clear_deleted_files.sh - 定时清理被进程占用的已删除文件
LOG_FILE="/var/log/cleanup_deleted_files.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] 开始检查被占用的已删除文件..." >> "$LOG_FILE"
# 使用 lsof +L1 查找 link count 为 0(即已删除)但仍被打开的文件
DELETED_ENTRIES=$(lsof +L1 2>/dev/null | grep -v "COMMAND")
if [ -z "$DELETED_ENTRIES" ]; then
echo "[$DATE] 未发现被占用的已删除文件。" >> "$LOG_FILE"
exit 0
fi
echo "[$DATE] 发现以下被占用的已删除文件:" >> "$LOG_FILE"
echo "$DELETED_ENTRIES" >> "$LOG_FILE"
# 提取唯一 PID 列表
PIDS=$(echo "$DELETED_ENTRIES" | awk 'NR>1 {print $2}' | sort -u)
for PID in $PIDS; do
if ! kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] PID $PID 已不存在,跳过。" >> "$LOG_FILE"
continue
fi
CMD=$(ps -p "$PID" -o comm= 2>/dev/null | tr -d ' ')
echo "[$DATE] 处理进程: PID=$PID, CMD=$CMD" >> "$LOG_FILE"
# 尝试发送 SIGHUP(适用于 Nginx、rsyslog 等支持 reload 的服务)
if kill -0 "$PID" 2>/dev/null; then
echo "[$DATE] 向 PID $PID 发送 SIGHUP 信号..." >> "$LOG_FILE"
kill -HUP "$PID" 2>/dev/null && continue
fi
# 若 SIGHUP 无效或不支持,记录警告(不强制 kill,避免服务中断)
echo "[$DATE] WARNING: 无法通过 SIGHUP 释放 PID $PID 的文件句柄。建议手动处理或配置 logrotate。" >> "$LOG_FILE"
done
echo "[$DATE] 检查完成。" >> "$LOG_FILE"
#!/bin/bash
# 宿主机上的脚本:检查 EMQX,如果容器未运行则重启 uemqx 容器
LOG_FILE="/var/log/monitor_emqx_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
check_emqx() {
# 检查 uemqx 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 通过 docker exec 检查 EMQX 进程是否在容器内运行
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
# 检查EMQX是否在运行状态(使用EMQX自带的命令)
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
# 额外验证EMQX是否真正可用
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "EMQX 服务状态正常"
return 0
else
log "警告: emqx_ctl 命令执行成功,但返回意外状态"
return 1
fi
else
log "警告: 容器正在运行,EMQX 进程存在,但 emqx_ctl 命令执行失败"
return 1
fi
else
log "警告: 容器正在运行,但在容器内未找到 EMQX 进程"
return 1
fi
else
log "信息: uemqx 容器未运行"
return 1
fi
}
restart_emqx_container() {
log "EMQX 未运行。正在尝试重启容器 'uemqx'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uemqx"; then
# 停止可能挂起的容器
docker stop uemqx >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uemqx; then
log "成功: EMQX 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 30 秒让 EMQX 服务完全启动..."
for i in {1..30}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uemqx"; then
log "信息: EMQX 容器现在正在运行。"
# 再次检查EMQX进程是否已启动
if docker exec uemqx pgrep -f "emqx" >/dev/null 2>&1; then
log "信息: EMQX 进程在容器内正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
if docker exec uemqx emqx_ctl status >/dev/null 2>&1; then
status_output=$(docker exec uemqx emqx_ctl status 2>&1)
if echo "$status_output" | grep -q "is started"; then
log "信息: EMQX 服务状态正常。"
return 0
else
log "错误: EMQX 进程运行中,但服务状态异常。"
return 1
fi
else
log "错误: EMQX 进程运行中,但服务状态检查失败。"
return 1
fi
else
log "错误: EMQX 进程在容器内未运行。"
return 1
fi
else
log "错误: EMQX 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 EMQX 容器。"
return 1
fi
else
log "错误: 容器 'uemqx' 不存在!"
log "信息: 您可能需要手动重新创建 EMQX 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 EMQX 服务状态..."
if check_emqx; then
log "EMQX 正在运行且状态正常。"
else
log "EMQX 无响应或容器未运行。"
restart_emqx_container
# 检查重启后是否正常工作
if check_emqx; then
log "EMQX 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 EMQX 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uemqx"
fi
fi
\ No newline at end of file
#!/bin/bash
# --- 配置区域 ---
# 日志文件路径
LOG_FILE="/var/log/monitor_external_api_services.log"
# 定义要监控的服务及其相关信息
# 格式: "进程名:目录路径:启动脚本路径"
SERVICES=(
"ubains-meeting-api-1.0-SNAPSHOT.jar:/var/www/java/external-meeting-api:/var/www/java/external-meeting-api/run.sh"
"malan:/var/www/malan:/var/www/malan/run.sh"
)
# --- 函数定义 ---
# 记录日志的函数
log_message() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}
# 检查进程是否运行
is_process_running() {
local process_name="$1"
# 使用 pgrep -f 搜索命令行中包含该名称的进程
# 对于 .jar 文件,通常搜索的是 java -jar ...<jar_name>
# 对于其他程序,搜索其进程名
if [[ "$process_name" == *.jar ]]; then
# 如果是 JAR 文件,搜索 java 进程中包含该 jar 名称的
pgrep -f "java.*$process_name" > /dev/null
else
# 否则直接搜索进程名
pgrep -x "$process_name" > /dev/null
fi
if [ $? -eq 0 ]; then
return 0 # 进程运行中
else
return 1 # 进程未运行
fi
}
# 检查目录是否存在
is_directory_exists() {
local dir_path="$1"
[ -d "$dir_path" ]
}
# 检查启动脚本是否存在且可执行
is_script_executable() {
local script_path="$1"
[ -x "$script_path" ]
}
# 启动服务
start_service() {
local service_name="$1"
local dir_path="$2"
local script_path="$3"
log_message "尝试启动服务 '$service_name'..."
# 切换到服务目录并执行启动脚本
# 使用子shell (cd ...) 以确保不影响当前脚本的工作目录
(
cd "$dir_path" || { log_message "错误: 无法切换到目录 '$dir_path'"; return 1; }
# 检查启动脚本是否存在且可执行
if ! is_script_executable "$script_path"; then
log_message "错误: 启动脚本 '$script_path' 不存在或不可执行。"
return 1
fi
# 执行启动脚本
# 使用 nohup 将进程与终端脱离,使其在后台持续运行
# 输出重定向到 startup.log 或 /dev/null
nohup "./$(basename "$script_path")" > startup.log 2>&1 &
# 等待一小段时间,让进程有机会启动
sleep 3
# 再次检查进程是否启动成功
if is_process_running "$service_name"; then
log_message "服务 '$service_name' 启动成功。"
return 0
else
log_message "错误: 服务 '$service_name' 启动失败。"
return 1
fi
)
}
# --- 主逻辑 ---
# 初始化日志
log_message "=== 服务监控脚本开始执行 ==="
# 遍历所有服务
for service_info in "${SERVICES[@]}"; do
# 解析服务信息
IFS=':' read -r service_name dir_path script_path <<< "$service_info"
# 去除可能的前后空格
service_name=$(echo "$service_name" | xargs)
dir_path=$(echo "$dir_path" | xargs)
script_path=$(echo "$script_path" | xargs)
log_message "检查服务: $service_name (目录: $dir_path, 启动脚本: $script_path)"
# 检查目录是否存在
if ! is_directory_exists "$dir_path"; then
log_message "跳过服务 '$service_name': 目录 '$dir_path' 不存在。"
continue # 跳过当前循环,检查下一个服务
fi
# 检查进程是否运行
if is_process_running "$service_name"; then
log_message "服务 '$service_name' 正在运行。"
else
log_message "服务 '$service_name' 未运行。"
# 尝试启动服务
start_service "$service_name" "$dir_path" "$script_path"
fi
done
log_message "=== 服务监控脚本执行完毕 ==="
#!/bin/bash
# 宿主机上的脚本:检查 MySQL,如果容器未运行则重启 umysql 容器
LOG_FILE="/var/log/monitor_mysql_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
get_mysql_password() {
docker exec umysql printenv MYSQL_ROOT_PASSWORD 2>/dev/null
}
check_mysql() {
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
# 尝试连接数据库
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" 2>/dev/null; then
# 尝试执行一个简单的SQL查询来确认数据库功能正常
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "MySQL 服务连接正常,可以执行SQL查询"
return 0
else
log "警告: MySQL 服务可以ping通,但无法执行SQL查询"
return 1
fi
else
log "警告: 无法连接到 MySQL 服务"
return 1
fi
else
log "信息: umysql 容器未运行"
return 1
fi
}
restart_mysql_container() {
log "MySQL 未运行。正在尝试重启容器 'umysql'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "umysql"; then
# 停止可能挂起的容器
docker stop umysql >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start umysql; then
log "成功: MySQL 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 60 秒让 MySQL 服务完全启动..."
for i in {1..60}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "umysql"; then
log "信息: MySQL 容器现在正在运行。"
# 等待一段时间后检查服务状态
log "信息: 等待 20 秒后检查服务状态..."
sleep 20
local mysql_password
mysql_password=$(get_mysql_password)
if [ -z "$mysql_password" ]; then
return 1
fi
if docker exec umysql mysqladmin ping -h localhost -u root -p"$mysql_password" >/dev/null 2>&1; then
if docker exec umysql mysql -u root -p"$mysql_password" -e "SELECT 1;" >/dev/null 2>&1; then
log "信息: MySQL 服务状态正常。"
return 0
else
log "错误: MySQL 服务运行中,但无法执行SQL查询。"
return 1
fi
else
log "错误: MySQL 服务状态检查失败。"
return 1
fi
else
log "错误: MySQL 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 MySQL 容器。"
return 1
fi
else
log "错误: 容器 'umysql' 不存在!"
log "信息: 您可能需要手动重新创建 MySQL 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 MySQL 服务状态..."
if check_mysql; then
log "MySQL 正在运行且状态正常。"
else
log "MySQL 无响应或容器未运行。"
restart_mysql_container
# 检查重启后是否正常工作
if check_mysql; then
log "MySQL 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 MySQL 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs umysql"
fi
fi
\ No newline at end of file
#!/bin/bash
# 宿主机上的脚本:检查 Redis,如果容器未运行则重启 uredis 容器
LOG_FILE="/var/log/monitor_redis_service.log"
log() {
local message
message="$(date '+%Y-%m-%d %H:%M:%S') - $1"
echo "$message"
# 同时写入日志文件
echo "$message" >> "$LOG_FILE"
}
# 直接在脚本中定义 Redis 密码
REDIS_PASSWORD="dNrprU&2S"
check_redis() {
# 检查 uredis 容器是否正在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
# 首先尝试不使用密码的 ping 命令
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 无密码情况下能 ping 通
log "Redis 服务状态正常"
return 0
else
# 检查是否是认证问题
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
log "检测到需要认证的 Redis 服务,正在尝试使用密码..."
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "Redis 服务状态正常(已通过密码认证)"
return 0
else
log "警告: 使用密码认证成功,但 ping 返回意外状态: $ping_output"
return 1
fi
else
log "警告: 需要认证,但无法使用预设密码连接到 Redis"
return 1
fi
else
# 不是认证问题,可能是其他错误
log "警告: Redis 连接失败,错误信息: $auth_output"
return 1
fi
fi
else
log "信息: uredis 容器未运行"
return 1
fi
}
restart_redis_container() {
log "Redis 未运行。正在尝试重启容器 'uredis'..."
# 检查容器是否存在(不仅仅是运行状态)
if docker ps -a --format '{{.Names}}' | grep -Fxq "uredis"; then
# 停止可能挂起的容器
docker stop uredis >/dev/null 2>&1 || true
# 容器存在但未运行,尝试启动
if docker start uredis; then
log "成功: Redis 容器已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 无法启动 Redis 容器。"
# 尝试清理数据目录并重启
log "信息: 尝试清理数据目录并重新启动 Redis 容器..."
# 检查并删除可能存在的数据目录
if [ -d "/var/www/java/redis/data" ]; then
log "信息: 清理 /var/www/java/redis/data 目录..."
rm -rf /var/www/java/redis/data/*
fi
if [ -d "/var/www/redis/data" ]; then
log "信息: 清理 /var/www/redis/data 目录..."
rm -rf /var/www/redis/data/*
fi
# 再次尝试启动容器
log "信息: 再次尝试启动 Redis 容器..."
if docker start uredis; then
log "成功: Redis 容器在清理数据后已成功启动。"
# 等待几秒让服务启动
log "信息: 等待 20 秒让 Redis 服务完全启动..."
for i in {1..20}; do
echo -n "." >> "$LOG_FILE"
sleep 1
done
echo "" >> "$LOG_FILE"
# 检查启动后容器是否仍在运行
if docker ps --format '{{.Names}}' | grep -Fxq "uredis"; then
log "信息: Redis 容器现在正在运行。"
# 等待一段时间后再次检查服务状态
log "信息: 等待 10 秒后检查服务状态..."
sleep 10
# 再次检查是否需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
# 不需要认证
if docker exec uredis redis-cli ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
else
# 需要认证,尝试使用密码
auth_output=$(docker exec uredis redis-cli ping 2>&1)
if [[ "$auth_output" == *"NOAUTH"* ]] || [[ "$auth_output" == *"Authentication required"* ]]; then
# 使用硬编码的密码进行认证测试
if docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping >/dev/null 2>&1; then
ping_output=$(docker exec uredis redis-cli -a "$REDIS_PASSWORD" --no-auth-warning ping 2>&1)
if [ "$ping_output" = "PONG" ]; then
log "信息: Redis 服务状态正常(已通过密码认证)。"
return 0
else
log "错误: Redis 服务状态异常: $ping_output"
return 1
fi
else
log "错误: Redis 需要认证,但无法使用预设密码连接到 Redis。"
return 1
fi
else
log "错误: Redis 服务状态检查失败。"
return 1
fi
fi
else
log "错误: Redis 容器在启动后不久就停止了。"
return 1
fi
else
log "错误: 即使清理了数据目录,仍然无法启动 Redis 容器。"
return 1
fi
fi
else
log "错误: 容器 'uredis' 不存在!"
log "信息: 您可能需要手动重新创建 Redis 容器。"
return 1
fi
}
# 主逻辑
log "开始检查 Redis 服务状态..."
if check_redis; then
log "Redis 正在运行且状态正常。"
else
log "Redis 无响应或容器未运行。"
restart_redis_container
# 检查重启后是否正常工作
if check_redis; then
log "Redis 已成功重启,现在状态正常。"
else
log "错误: 重启尝试后 Redis 仍无响应。"
log "信息: 请使用以下命令检查容器日志: docker logs uredis"
fi
fi
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论