Skip to content

故障排查

本文档汇总了 MISEB 系统常见问题及解决方案。

快速诊断流程

遇到问题时,请按以下顺序排查:

1. 检查容器状态 → docker ps -a
2. 查看错误日志 → docker logs <容器名>
3. 检查网络连通 → docker network inspect
4. 检查资源使用 → docker stats
5. 检查端口占用 → netstat -tlnp

服务启动问题

脚本报错 $'\r': command not found

症状:执行启动脚本或读取配置文件时提示:

bash
.env: line 5: $'\r': command not found

bash
-bash: ./start.sh: /bin/bash^M: bad interpreter: No such file or directory

原因:文件在Windows环境下编辑或保存,换行符为 CRLF\r\n),而Linux仅识别 LF\n)。

解决方案

方法一:使用sed命令转换(推荐)

bash
# 转换单个文件
sed -i 's/\r$//' .env

# 批量转换所有脚本和配置文件
sed -i 's/\r$//' *.sh *.yml .env*

# 转换整个目录下的所有相关文件
find . -name "*.sh" -exec sed -i 's/\r$//' {} \;
find . -name "*.yml" -exec sed -i 's/\r$//' {} \;
find . -name ".env*" -exec sed -i 's/\r$//' {} \;

方法二:使用dos2unix工具

bash
# 安装dos2unix
# CentOS/RHEL
yum install -y dos2unix

# Ubuntu/Debian
apt-get install -y dos2unix

# 转换单个文件
dos2unix .env
dos2unix start.sh

# 批量转换
dos2unix *.sh *.yml .env*

方法三:使用tr命令

bash
# 转换文件
tr -d '\r' < .env > .env.tmp && mv .env.tmp .env

方法四:使用vim编辑器

bash
# 打开文件
vim .env

# 在vim中执行命令转换格式
:set ff=unix
:wq

预防措施

  • 在Windows上使用支持Unix换行符的编辑器(如VS Code、Notepad++)
  • VS Code中设置:文件 → 首选项 → 设置 → 搜索 "eol" → 选择 \n
  • Notepad++中:编辑 → 文档格式转换 → 转换为Unix格式

容器启动失败

症状:容器状态显示 ExitedRestarting

排查步骤

bash
# 1. 查看容器状态
docker ps -a

# 2. 查看容器日志
docker logs miseb-admin

# 3. 查看详细错误
docker logs --tail 100 miseb-admin

常见原因及解决方案

原因解决方案
内存不足调小JVM参数或增加服务器内存
端口被占用停止占用端口的服务或修改端口
配置错误检查.env文件配置
依赖服务未启动先启动基础设施服务

MySQL启动失败

症状miseb-mysql 容器启动失败

排查

bash
docker logs miseb-mysql

常见问题

  1. 权限问题
bash
# 检查数据目录权限
ls -la /var/lib/docker/volumes/miseb-mysql-data/

# 修复权限
docker run --rm -v miseb-mysql-data:/data alpine chown -R 999:999 /data
  1. 数据目录损坏
bash
# 备份数据后删除数据卷
docker volume rm miseb-mysql-data

# 重新创建并初始化
docker compose up -d mysql

Elasticsearch启动失败

症状:ES容器一直重启

排查

bash
docker logs miseb-elasticsearch

常见问题

  1. vm.max_map_count 太小
bash
# 临时设置
sudo sysctl -w vm.max_map_count=262144

# 永久设置
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
  1. 内存不足

修改 .env 文件:

bash
ES_JAVA_OPTS=-Xms256m -Xmx256m
  1. 数据目录权限
bash
docker run --rm -v miseb-es-data:/data alpine chown -R 1000:1000 /data

文件夹权限问题

症状

  • 容器启动失败,日志显示权限错误
  • 文件创建失败,提示 Permission denied
  • 无法写入文件夹或数据目录
  • 日志显示 Failed to create directoryCannot write to file

示例错误日志

java.io.IOException: Permission denied
Cannot create directory: /data/miseb/images/misebimage
Failed to write file: /data/miseb/images/ssl/server.crt

原因

Docker容器内的进程使用特定UID/GID运行,而宿主机挂载的目录权限与容器内进程的UID/GID不匹配,导致容器无法读写文件。

常见情况:

  • Nginx容器:运行用户为 nginx (UID: 101, GID: 101)
  • MySQL容器:运行用户为 mysql (UID: 999, GID: 999)
  • Elasticsearch容器:运行用户为 elasticsearch (UID: 1000, GID: 1000)
  • Java应用:通常以 root 运行,但某些镜像使用普通用户

解决方案

方法一:初始化时设置目录权限(推荐)

在首次部署时,使用脚本创建并设置正确权限:

bash
#!/bin/bash
# 创建所需目录
mkdir -p /data/miseb/images/{misebimage,uploadf,ssl,ssl/acme-challenge}
mkdir -p /data/miseb/mysql
mkdir -p /data/miseb/redis
mkdir -p /data/miseb/elasticsearch
mkdir -p /data/miseb/minio

# 设置通用权限(任何用户都可读写)
chmod -R 777 /data/miseb/images

# 为MySQL设置特定权限 (UID:999 GID:999)
chown -R 999:999 /data/miseb/mysql
chmod -R 755 /data/miseb/mysql

# 为Elasticsearch设置特定权限 (UID:1000 GID:1000)
chown -R 1000:1000 /data/miseb/elasticsearch
chmod -R 755 /data/miseb/elasticsearch

# 为Redis设置权限
chmod -R 755 /data/miseb/redis

# 为MinIO设置权限
chmod -R 755 /data/miseb/minio

echo "✓ 目录权限设置完成"

方法二:使用Docker临时容器修复权限

如果容器已经创建但因权限问题无法启动:

bash
# 修复图片目录权限
docker run --rm -v /data/miseb/images:/data alpine sh -c "chmod -R 777 /data"

# 修复MySQL数据目录权限
docker run --rm -v /data/miseb/mysql:/data alpine sh -c "chown -R 999:999 /data && chmod -R 755 /data"

# 修复Elasticsearch数据目录权限
docker run --rm -v /data/miseb/elasticsearch:/data alpine sh -c "chown -R 1000:1000 /data && chmod -R 755 /data"

方法三:使用Docker Volume方式(推荐生产环境)

docker-compose.yml 中使用命名卷而不是绑定挂载:

yaml
services:
  admin:
    volumes:
      # 使用命名卷(Docker自动管理权限)
      - miseb-images:/data/miseb/images

  mysql:
    volumes:
      - miseb-mysql-data:/var/lib/mysql

volumes:
  miseb-images:
    driver: local
  miseb-mysql-data:
    driver: local

方法四:在Dockerfile中预设权限

对于需要特定权限的目录,在构建镜像时就创建好:

dockerfile
# 创建目录并设置权限
RUN mkdir -p /data/miseb/images/ssl && \
    chmod -R 777 /data/miseb/images

验证权限是否正确

bash
# 检查宿主机目录权限
ls -la /data/miseb/images/

# 检查容器内目录权限
docker exec miseb-nginx ls -la /data/miseb/images/

# 检查容器运行用户
docker exec miseb-nginx whoami
docker exec miseb-nginx id

常见目录权限配置表

目录推荐权限所有者说明
/data/miseb/images/misebimage777任意商品图片上传目录
/data/miseb/images/uploadf777任意文件上传目录
/data/miseb/images/ssl755任意SSL证书目录
/data/miseb/mysql755999:999MySQL数据目录
/data/miseb/redis755任意Redis数据目录
/data/miseb/elasticsearch7551000:1000ES数据目录
/data/miseb/minio755任意MinIO存储目录

最佳实践

  1. 开发环境:使用 chmod 777 简化权限管理
  2. 生产环境:使用最小权限原则 + Docker Volume
  3. 安全建议:避免在生产环境中使用 777 权限,使用精确的UID/GID匹配
  4. 自动化:在部署脚本中包含权限设置步骤

SELinux注意事项

如果服务器启用了SELinux,还需要设置SELinux上下文:

bash
# 临时关闭SELinux(测试用)
setenforce 0

# 或为目录设置正确的SELinux上下文
chcon -Rt svirt_sandbox_file_t /data/miseb/

永久关闭SELinux(不推荐生产环境):

bash
# 编辑 /etc/selinux/config
SELINUX=disabled

Java服务OOM

症状:日志显示 OutOfMemoryError

解决方案

  1. 调整JVM内存配置:
bash
# 修改 .env
ADMIN_JAVA_OPTS=-Xms256m -Xmx512m -XX:+UseG1GC
FRONT_JAVA_OPTS=-Xms256m -Xmx512m -XX:+UseG1GC
  1. 重启服务:
bash
docker compose up -d --force-recreate

连接问题

数据库连接失败

症状:日志显示 Communications link failureConnection refused

排查

bash
# 1. 检查MySQL是否运行
docker ps | grep mysql

# 2. 测试连接
docker exec miseb-admin ping -c 3 mysql

# 3. 检查MySQL日志
docker logs miseb-mysql

解决方案

  1. 确保MySQL已启动:
bash
docker compose up -d mysql
  1. 等待MySQL就绪:
bash
until docker exec miseb-mysql mysqladmin ping -h localhost --silent; do
    echo "等待MySQL启动..."
    sleep 5
done
  1. 检查用户权限:
bash
docker exec miseb-mysql mysql -uroot -p -e "SELECT user, host FROM mysql.user;"

Redis连接失败

症状:日志显示 Unable to connect to Redis

排查

bash
# 1. 检查Redis状态
docker ps | grep redis

# 2. 测试连接
docker exec miseb-redis redis-cli -a 'password' ping

解决方案

  1. 确保Redis已启动
  2. 检查密码配置是否正确
  3. 检查网络连通性

容器间网络不通

症状:容器之间无法互相访问

排查

bash
# 查看网络
docker network ls

# 查看容器所在网络
docker inspect miseb-admin | grep -A 20 "Networks"

# 查看网络详情
docker network inspect miseb-network

解决方案

确保所有容器在同一网络:

bash
# 将容器连接到网络
docker network connect miseb-network miseb-admin

访问问题

页面404

症状:访问页面返回404错误

排查

bash
# 1. 检查Nginx状态
docker ps | grep nginx

# 2. 检查Nginx配置
docker exec miseb-nginx nginx -t

# 3. 检查静态文件
docker exec miseb-nginx ls -la /usr/share/nginx/html/

解决方案

  1. 重载Nginx配置:
bash
docker exec miseb-nginx nginx -s reload
  1. 检查前端文件是否正确部署

API请求失败

症状:API返回500错误或超时

排查

bash
# 1. 检查后端健康状态
curl -v http://localhost:8080/actuator/health
curl -v http://localhost:8081/actuator/health

# 2. 查看后端日志
docker logs --tail 100 miseb-admin
docker logs --tail 100 miseb-front

解决方案

  1. 检查数据库连接
  2. 检查Redis连接
  3. 查看详细错误日志

上传文件失败

症状:文件上传返回错误

排查

bash
# 检查MinIO状态
curl http://localhost:9000/minio/health/live

# 检查MinIO日志
docker logs miseb-minio

解决方案

  1. 检查MinIO配置
  2. 检查存储空间
  3. 检查文件大小限制

性能问题

响应缓慢

症状:页面加载或API响应很慢

排查

bash
# 1. 查看资源使用情况
docker stats --no-stream

# 2. 查看系统负载
top -bn1 | head -20

# 3. 查看磁盘IO
iostat -x 1 5

解决方案

  1. 内存不足:增加服务器内存或优化JVM配置
  2. CPU过高:检查是否有异常进程
  3. 磁盘IO高:考虑使用SSD
  4. 网络问题:检查带宽使用

内存占用过高

症状docker stats 显示内存使用率很高

解决方案

  1. 优化JVM配置:
bash
# 减小堆内存
ADMIN_JAVA_OPTS=-Xms256m -Xmx512m
FRONT_JAVA_OPTS=-Xms256m -Xmx512m
ES_JAVA_OPTS=-Xms256m -Xmx256m
  1. 清理缓存:
bash
# 清理Redis缓存(谨慎操作)
docker exec miseb-redis redis-cli -a 'password' FLUSHDB

磁盘空间不足

症状:服务异常,日志显示磁盘空间不足

排查

bash
# 查看磁盘使用
df -h

# 查看Docker占用
docker system df

# 查看大文件
du -sh /* | sort -rh | head -20

解决方案

  1. 清理Docker资源:
bash
# 清理未使用的镜像
docker image prune -a

# 清理未使用的容器
docker container prune

# 清理构建缓存
docker builder prune
  1. 清理日志文件:
bash
# 查找大日志文件
find /var/lib/docker/containers -name "*.log" -size +100M

# 清空日志文件
truncate -s 0 /var/lib/docker/containers/<container-id>/*.log

日志分析

常见错误日志

Connection refused

java.net.ConnectException: Connection refused

原因:目标服务未启动或端口不正确

解决:检查目标服务状态和端口配置

Access denied

java.sql.SQLException: Access denied for user

原因:数据库用户名或密码错误

解决:检查 .env 中的数据库配置

No space left on device

Error: No space left on device

原因:磁盘空间不足

解决:清理磁盘空间

Out of memory

java.lang.OutOfMemoryError: Java heap space

原因:JVM堆内存不足

解决:增加JVM堆内存配置

恢复操作

重置服务

如果问题无法解决,可以尝试重置服务:

bash
# 停止所有服务
./stop.sh

# 删除容器(保留数据)
docker compose down

# 重新启动
./start.sh

完全重置(危险)

警告

以下操作会删除所有数据,请先备份!

bash
# 停止并删除所有容器和数据卷
docker compose down -v

# 重新部署
./start.sh

获取帮助

如果以上方法都无法解决问题,请收集以下信息后联系技术支持:

  1. 系统信息
bash
uname -a
docker version
docker compose version
  1. 容器状态
bash
docker ps -a
  1. 错误日志
bash
docker logs --tail 500 miseb-admin > admin.log
docker logs --tail 500 miseb-front > front.log
  1. 资源使用
bash
docker stats --no-stream > stats.log
free -m
df -h

数据库迁移问题

Flyway迁移失败

症状

  • 应用启动时报错 FlywayException
  • 日志显示 Migration checksum mismatch
  • 数据库迁移脚本执行失败
  • flyway_schema_history 表中有失败记录(success=0)

示例错误日志

org.flywaydb.core.api.FlywayException: Validate failed:
Migration checksum mismatch for migration version 1.0.1

org.flywaydb.core.internal.command.DbMigrate$FlywayMigrateException:
Migration V1.0.1__Init_migration_config.sql failed

原因

  1. 迁移脚本被修改:已执行的迁移脚本内容被修改,导致校验和不匹配
  2. 迁移执行失败:SQL语法错误、权限不足、数据冲突等导致迁移中断
  3. 手动修改数据库:直接修改了数据库结构,与迁移脚本不一致
  4. 版本回退:回退到旧版本后,新版本的迁移记录仍存在

解决方案

我们提供了专门的Flyway修复工具,可以快速解决迁移失败问题。

使用修复工具(推荐)

Linux/Mac系统

bash
# 进入部署目录
cd deploy

# 运行修复脚本
./fix-flyway.sh

Windows系统

bash
# 进入部署目录
cd deploy

# 运行修复脚本
fix-flyway.bat

修复工具功能

修复工具提供以下功能:

  1. 查看失败的迁移记录

    • 显示所有执行失败的迁移版本
    • 查看失败原因和执行时间
  2. 查看所有迁移记录

    • 显示最近20条迁移历史
    • 查看迁移状态和版本信息
  3. 删除失败的迁移记录

    • 自动删除所有失败的迁移记录
    • 允许应用重新执行迁移
  4. 删除指定版本的迁移记录

    • 精确删除某个版本的迁移记录
    • 适用于需要重新执行特定版本的场景
  5. 重置Flyway历史表

    • 完全删除 flyway_schema_history
    • 适用于需要完全重新初始化的场景(危险操作)
  6. 重启Admin服务

    • 自动重启Admin服务触发迁移
    • 方便验证修复结果

使用示例

场景1:删除失败的迁移记录

bash
# 运行修复工具
./fix-flyway.sh

# 选择操作
请输入选项 (0-6): 1  # 先查看失败记录

# 确认后删除
请输入选项 (0-6): 3  # 删除所有失败记录
是否继续? (y/n): y

# 重启服务触发重新迁移
请输入选项 (0-6): 6  # 重启Admin服务

场景2:删除指定版本的迁移记录

bash
./fix-flyway.sh

请输入选项 (0-6): 4  # 删除指定版本
版本号: 1.0.1
是否继续? (y/n): y

场景3:完全重置(慎用)

bash
./fix-flyway.sh

请输入选项 (0-6): 5  # 重置Flyway历史表
是否继续? (y/n): y

手动修复方法

如果无法使用修复工具,也可以手动执行SQL:

1. 查看失败的迁移记录

sql
SELECT
    installed_rank AS '序号',
    version AS '版本',
    description AS '描述',
    success AS '状态',
    installed_on AS '执行时间'
FROM flyway_schema_history
WHERE success = 0;

2. 删除失败的迁移记录

sql
-- 删除所有失败记录
DELETE FROM flyway_schema_history WHERE success = 0;

-- 或删除指定版本
DELETE FROM flyway_schema_history WHERE version = '1.0.1';

3. 重启应用触发重新迁移

bash
docker compose restart miseb-admin

4. 验证迁移结果

bash
# 查看日志
docker compose logs -f miseb-admin

# 查看迁移历史
docker exec miseb-mysql mysql -u root -p"$MYSQL_ROOT_PASSWORD" miseb -e \
  "SELECT version, description, success FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 10;"

预防措施

  1. 不要修改已执行的迁移脚本

    • 已执行的迁移脚本不应再修改
    • 新的变更应创建新的迁移脚本
  2. 测试迁移脚本

    • 在开发环境充分测试后再部署
    • 确保SQL语法正确且兼容
  3. 备份数据库

    • 执行迁移前先备份数据库
    • 出现问题可以快速恢复
  4. 使用事务

    • 迁移脚本中使用事务确保原子性
    • 失败时自动回滚
  5. 监控迁移日志

    • 部署后及时查看迁移日志
    • 发现问题立即处理

最佳实践

  • 开发环境:使用修复工具快速解决问题
  • 生产环境:先备份数据库,再使用修复工具
  • 重要提示:删除迁移记录后,应用会重新执行该版本的迁移脚本

注意事项

  1. 删除迁移记录不会回滚已执行的SQL操作
  2. 如果数据库结构已被修改,重新执行迁移可能失败
  3. 重置Flyway历史表是危险操作,仅在确认需要时使用
  4. 生产环境操作前务必备份数据库

联系方式

成都艾唯特软件有限公司