# 运维常用命令 > 服务地址:`http://<内网IP>:5019` ## 1. 服务管理 ```bash # 启动所有服务 docker compose up -d # 停止所有服务 docker compose down # 重启所有服务 docker compose restart # 重启单个服务 docker compose restart app docker compose restart queue docker compose restart pdf-worker # 查看运行状态 docker compose ps # 查看进程状态(nginx + php-fpm) docker exec math_cms_app ps aux | grep -E "nginx|php-fpm" ``` ## 2. 日志查看 ### 快速调试命令 ```bash # 1. 查看 Laravel 应用日志(最常用) docker exec math_cms_app tail -100 storage/logs/laravel.log # 实时查看 docker exec math_cms_app tail -f storage/logs/laravel.log # 2. 查看容器日志(Nginx + PHP-FPM) docker logs math_cms_app --tail 100 # 实时查看 docker logs -f math_cms_app # 3. 查看 PHP 错误日志 docker exec math_cms_app tail -100 /var/log/php-fpm/error.log # 4. 查看 Nginx 错误日志 docker exec math_cms_app tail -100 /var/log/nginx/error.log # 5. 筛选特定关键词 docker exec math_cms_app tail -500 storage/logs/laravel.log | grep -i "error\|exception\|fail" # 6. 查看今天的日志(如果按日期分割) docker exec math_cms_app cat storage/logs/laravel-$(date +%Y-%m-%d).log | tail -100 # 7. 快速排查智能组卷问题 docker exec math_cms_app tail -200 storage/logs/laravel.log | grep -i "智能\|intelligent\|assemble\|error" ``` ### Laravel 应用日志 ```bash # 查看最近日志 docker exec math_cms_app tail -100 storage/logs/laravel.log # 只看 ERROR 级别 docker exec math_cms_app grep "\.ERROR" storage/logs/laravel.log | tail -50 # 实时监控日志 docker exec math_cms_app tail -f storage/logs/laravel.log # 清空日志 docker exec math_cms_app truncate -s 0 storage/logs/laravel.log # 组合:先显示最近 200 行,然后实时监控 docker exec math_cms_app tail -200f storage/logs/laravel.log ``` ### Nginx 日志 ```bash # 访问日志(看请求状态码) docker exec math_cms_app tail -100 /var/log/nginx/access.log # 错误日志 docker exec math_cms_app tail -50 /var/log/nginx/error.log # 只看 5xx 错误的请求 docker exec math_cms_app grep '" 5[0-9][0-9] ' /var/log/nginx/access.log | tail -30 ``` ### PHP-FPM 日志 ```bash # 慢请求日志(超过5秒的请求) docker exec math_cms_app cat /var/log/php-fpm-slow.log 2>/dev/null || echo "暂无慢请求" ``` ### 队列日志 ```bash # 查看队列 Worker 日志 docker logs math_cms_queue --tail=50 docker logs math_cms_pdf --tail=50 # 实时监控 PDF 队列 docker logs -f math_cms_pdf ``` ### 一键查看错误 ```bash docker exec math_cms_app sh -c "echo '=== Laravel Errors ===' && grep '\.ERROR' storage/logs/laravel.log | tail -10 && echo '=== Nginx 5xx ===' && grep '\" 5[0-9][0-9] ' /var/log/nginx/access.log | tail -5" ``` ## 3. 代码更新部署 ### 部署模式说明 系统支持两种部署模式: | 模式 | 说明 | 适用场景 | 耗时 | |------|------|---------|------| | **Quick** | 代码卷映射,无需重新构建 | 日常代码更新 | 10-30秒 | | **Build** | 完整构建 Docker 镜像 | 首次部署、依赖更新、Dockerfile 变更 | 5-10分钟 | ### 服务器与配置文件对应关系 | 服务器类型 | 基础文件 | Mount 文件 | |-----------|---------|-----------| | 主服务器 | `docker-compose.yml` | `docker-compose.mount.yml` | | PDF 服务器 | `docker-compose.pdf.yml` | `docker-compose.pdf.mount.yml` | | API 服务器 | `docker-compose.api.yml` | `docker-compose.api.mount.yml` | ### Ansible 自动部署(推荐) ```bash cd ansible # 快速部署(默认) ./deploy.sh # 所有服务器 ./deploy.sh quick pdf # 只部署 PDF 服务器 ./deploy.sh quick api # 只部署 API 服务器 ./deploy.sh quick main # 只部署主服务器 # 完整构建 ./deploy.sh build # 所有服务器 ./deploy.sh build pdf # 只部署 PDF 服务器 ./deploy.sh build api # 只部署 API 服务器 ./deploy.sh build main # 只部署主服务器 # 其他命令 ./deploy.sh test # 测试服务器连接 ./deploy.sh status # 查看服务器状态 ./deploy.sh help # 查看帮助 ``` ### 手动部署 - 主服务器 ```bash # Build 模式(完整构建) docker compose -f docker-compose.yml build docker compose -f docker-compose.yml up -d --force-recreate # Quick 模式(代码卷映射) docker compose -f docker-compose.yml -f docker-compose.mount.yml up -d --force-recreate ``` ### 手动部署 - PDF 服务器 ```bash # Build 模式(完整构建) docker compose -f docker-compose.pdf.yml build docker compose -f docker-compose.pdf.yml up -d --force-recreate # Quick 模式(代码卷映射) docker compose -f docker-compose.pdf.yml -f docker-compose.pdf.mount.yml up -d --force-recreate ``` ### 手动部署 - API 服务器 ```bash # Build 模式(完整构建) docker compose -f docker-compose.api.yml build docker compose -f docker-compose.api.yml up -d --force-recreate # Quick 模式(代码卷映射) docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d --force-recreate ``` ### 首次部署流程 首次部署必须先 build 创建镜像,之后才能使用 quick 模式: ```bash # 1. 拉取代码 git clone /srv/www/math_cms cd /srv/www/math_cms # 2. 配置环境 cp .env.example .env # 编辑 .env 配置数据库等 # 3. 构建镜像(以 API 服务器为例) docker compose -f docker-compose.api.yml build # 4. 启动容器(使用 quick 模式) docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d ``` ### 日常更新流程(Quick 模式) ```bash # 1. 拉取最新代码 git fetch origin && git reset --hard origin/main # 2. 重启容器(以 API 服务器为例) docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d --force-recreate # 3. 清除缓存 docker exec math_cms_app php artisan optimize:clear ``` ### 注意事项 1. **Quick 模式前提**:必须先执行过 `build`,镜像里有 vendor、node_modules、public/build 2. **Queue Worker**:是常驻进程,代码更新后必须重启容器才能生效 3. **Mount 文件作用**:覆盖 volumes 配置,将宿主机代码映射到容器,但排除 vendor 等目录(用镜像里的) ## 4. 缓存清理 ```bash # 进入容器清理 Laravel 缓存 docker exec math_cms_app php artisan optimize:clear # 重启队列(代码更新后必须) docker compose restart queue pdf-worker # 清理临时文件 docker exec math_cms_app rm -rf storage/app/temp/* ``` ## 5. 问题排查 ```bash # 查看容器资源使用 docker stats --no-stream # 进入容器调试 docker exec -it math_cms_app sh # 测试数据库连接 docker exec math_cms_app php artisan db:show # 测试 Redis 连接 docker exec math_cms_app php artisan tinker --execute="dump(app('redis')->ping());" # 测试 Chrome(PDF 生成) docker exec math_cms_pdf chromium-browser --version # 查看失败的队列任务 docker exec math_cms_app php artisan queue:failed # 重试失败的任务 docker exec math_cms_app php artisan queue:retry all # 查看失败任务详情 docker exec math_cms_app php artisan tinker --execute="\$job = DB::table('failed_jobs')->latest()->first(); echo \$job->exception ?? 'no failed jobs';" ``` ## 6. 紧急处理 ```bash # CPU 满载 - 停止 PDF 服务 docker compose stop pdf-worker # 强制杀死所有 Chrome 进程 docker exec math_cms_pdf pkill -9 chromium # 清理临时文件 docker exec math_cms_pdf rm -rf /tmp/chrome-profile-* docker exec math_cms_pdf rm -rf /tmp/exam_pdf_* # 重启 PDF 服务 docker compose restart pdf-worker # 修复 storage 权限问题 docker exec math_cms_app chmod -R 777 /app/storage ``` ## 7. 健康检查 ```bash # 检查 Web 服务 curl http://localhost:5019/health # 检查容器状态 docker compose ps # 检查容器健康状态 docker inspect --format='{{.State.Health.Status}}' math_cms_app docker inspect --format='{{.State.Health.Status}}' math_cms_queue docker inspect --format='{{.State.Health.Status}}' math_cms_pdf # 检查 PHP-FPM 进程数 docker exec math_cms_app ps aux | grep php-fpm | wc -l # 检查 Nginx Worker 数 docker exec math_cms_app ps aux | grep nginx ``` ## 8. 备份与恢复 ```bash # 备份日志 cp -r storage/logs storage/logs_backup_$(date +%Y%m%d) # 备份上传文件 cp -r storage/app/public storage/app/public_backup_$(date +%Y%m%d) ``` ## 9. 定时任务(加入 crontab) ```bash # 清理临时文件(每小时) 0 * * * * cd /path/to/math_cms && rm -rf storage/app/temp/* 2>/dev/null # 清理旧日志(每天凌晨 3 点) 0 3 * * * find /path/to/math_cms/storage/logs -name "*.log" -mtime +7 -delete ``` ## 10. 容器资源限制 ```bash # 查看资源限制 docker inspect math_cms_pdf --format='{{.HostConfig.Memory}}' # 临时调整资源限制 docker update --cpus=1 --memory=1g math_cms_pdf ``` --- ## 服务架构 ``` ┌──────────────────────────────────────────────────────────────────┐ │ Docker Compose │ │ ┌──────────────────┐ ┌───────────────┐ ┌──────────────────────┐ │ │ │ math_cms_app │ │ math_cms_queue│ │ math_cms_pdf │ │ │ │ (Nginx+PHP-FPM) │ │ (Queue Worker)│ │ (PDF Worker) │ │ │ │ :5019 → :8000 │ │ default 队列 │ │ pdf 队列 │ │ │ 并发: 30 worker │ │ CPU:1 Mem:512M│ │ CPU:2 Mem:2G │ │ │ └──────────────────┘ └───────────────┘ └──────────────────────┘ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────┴─────────────────────┘ │ ┌──────────────────┴──────────────────┐ ▼ ▼ ┌──────────┐ ┌──────────┐ │ Redis │ │ MySQL │ │ (阿里云) │ │ (阿里云) │ └──────────┘ └──────────┘ ``` ### 队列说明 | 队列 | 容器 | 处理任务 | |------|------|---------| | default | math_cms_queue | AI批改、知识点匹配、题目导入等 | | pdf | math_cms_pdf | PDF生成(需要Chrome) | --- ## 11. PDF 生成问题排查 ### 常见问题 **问题1: PDF生成超时(50秒后失败)** - 原因:HTML模板中引用了CDN资源(KaTeX CSS/JS),容器内网络请求慢 - 解决:代码已优化,使用服务端 Node.js KaTeX 预渲染公式 **问题2: 公式显示为原始 LaTeX 文本** - 原因:Chrome headless 的 --print-to-pdf 不等待 JavaScript 执行 - 解决:使用 Node.js KaTeX 在服务端预渲染公式,生成静态 HTML **问题3: dbus 连接错误** - 表现:日志中出现 `Failed to connect to the bus` 错误 - 解决:docker-entrypoint.sh 已配置自动启动 dbus-daemon **问题4: Chrome 进程积累导致 CPU 满载** - 原因:PDF生成任务积压,Chrome进程未正常退出 - 解决: ```bash # 强制清理Chrome进程 docker exec math_cms_pdf pkill -9 chromium # 清理临时文件 docker exec math_cms_pdf rm -rf /tmp/chrome-profile-* /tmp/exam_* # 重启PDF服务 docker compose restart pdf-worker ``` **问题5: 日志为空(权限问题)** - 原因:storage 目录权限不正确,php-fpm 无法写入 - 解决: ```bash docker exec math_cms_app chmod -R 777 /app/storage ``` **问题6: GenerateAnalysisPdfJob 失败** - 原因:Job 未指定 pdf 队列,被 default 队列处理(无 Chrome) - 解决:代码已修复,Job 使用 `$this->onQueue('pdf')` ### PDF 生成调试 ```bash # 查看PDF生成日志 docker exec math_cms_app grep -i "ExamPdfExportService" storage/logs/laravel.log | tail -50 # 查看KaTeX渲染日志 docker exec math_cms_app grep -i "KatexRenderer\|LaTeX.*预渲染" storage/logs/laravel.log | tail -20 # 测试Node.js KaTeX是否正常工作 docker exec math_cms_app sh -c "echo '\$x^2 + y^2 = z^2\$' | node /app/scripts/katex-render.mjs" # 测试Chrome是否正常工作 docker exec math_cms_pdf chromium-browser --headless --disable-gpu --no-sandbox --print-to-pdf=/tmp/test.pdf https://www.baidu.com # 检查Chrome版本 docker exec math_cms_pdf chromium-browser --version # 检查Node.js版本 docker exec math_cms_app node --version # 检查dbus状态 docker exec math_cms_pdf pgrep -a dbus # 查看 PDF 队列处理情况 docker logs math_cms_pdf --tail=30 ``` --- ## 12. 并发问题排查 ### 试卷保存失败(题目数量不匹配) 错误信息:`题目插入数量不匹配:预期 20,实际 40` **原因:** 并发请求导致 Paper ID 碰撞,两个请求插入到同一个 paper_id **解决:** 已优化 PaperIdGenerator,增加进程ID区分不同 PHP-FPM Worker **排查命令:** ```bash # 查看相关错误 docker exec math_cms_app grep "题目插入数量不匹配" storage/logs/laravel.log | tail -10 ``` --- ## 联系方式 如有问题请联系开发团队。