今天的任务从“如何手动更新 Whoosh 索引”开始,最终成功落地了一套稳定、自动化、资源可控的定时索引更新方案。以下是全过程的关键知识点和踩坑复盘,供日后参考。
| 步骤 | 操作内容 | 关键命令/文件 |
|---|---|---|
| 1. 手动更新索引 | 确认自定义后端(Jieba分词)正常工作 | python3 manage.py update_index |
| 2. 设置定时任务 | 配置 Crontab 实现每日凌晨3点自动更新 | crontab -e |
| 3. 解决用户切换问题 | www-data 用户默认 Shell 为 nologin,改用 su -s /bin/bash | su -s /bin/bash - www-data -c "..." |
| 4. 添加日志时间戳 | 每次执行前记录日期,方便追踪 | 在命令中加入 (date && ...) |
| 5. 服务器资源优化 | 解决轻量云服务器因资源耗尽“死机”的问题 | 见下文“三大优化措施” |
| 6. 验证与清理 | 检查索引完整性,删除残留锁文件 | find ... -name "*.lock" -delete |
su - www-data 报错 This account is currently not available.原因:www-data 用户的默认 Shell 是 /usr/sbin/nologin,su - 尝试加载登录 Shell 被拒绝。
解决:改用 su -s /bin/bash - www-data -c "..." 指定可用 Shell,或使用 sudo -u www-data bash -c "..."。
原因:日志文件或父目录权限不足。
解决:提前创建日志文件并授权给 www-data 用户:
根源:vm.swappiness=0 导致系统拒绝使用 Swap,内存耗尽后触发 OOM Killer。
解决:启用 Swap 使用 + CPU限制 + Whoosh内存限制(见下文)。
| 优化方向 | 具体操作 | 效果 |
|---|---|---|
| 1. 启用 Swap 使用 | sysctl vm.swappiness=30 并永久生效 | 物理内存不足时,主动将冷数据挪到 Swap,防止 OOM |
| 2. 限制 CPU 使用率 | Crontab 中加入 cpulimit -l 50 -- | 防止索引构建时 CPU 飙升至 100%,导致系统卡顿 |
| 3. 限制 Whoosh 内存 | 自定义 Backend 中设置 writer = ix.writer(limitmb=64) | 控制索引写入时的内存缓冲区大小,避免内存突增 |
这条命令具备:
✅ 自动切换用户(www-data)
✅ 进入项目目录
✅ 记录执行时间
✅ 限制 CPU 使用率(50%)
✅ 使用虚拟环境 Python
✅ 日志重定向(含错误输出)
| 场景 | 命令 / 操作 |
|---|---|
| 手动增量更新 | python3 manage.py update_index |
| 手动全量重建 | python3 manage.py rebuild_index --noinput |
| 查看内存与 Swap | free -m |
| 查看系统 swappiness | cat /proc/sys/vm/swappiness |
| 调整 swappiness(临时) | sudo sysctl vm.swappiness=30 |
| 调整 swappiness(永久) | echo "vm.swappiness=30" >> /etc/sysctl.conf |
| 删除 Whoosh 残留锁文件 | find /path/to/whoosh_index/ -name "*.lock" -delete |
| 修改代码后刷新 Django 进程 | touch /path/to/project/wsgi.py |
| 查看 Crontab 日志 | tail -f /var/log/django_update_index.log |
监控凌晨3点的执行日志:明天查看 /var/log/django_update_index.log,确认时间戳和 Indexing X articles 正常输出。
如再次出现 Process dead!:那是 cpulimit 的正常结束通知,无需担心。
若索引更新后搜索结果未更新:检查是否因内存不足导致更新中断,可手动执行 rebuild_index。
长期维护:定期检查日志文件大小(可配合 logrotate 进行切割)。
今天成功完成了一套从 手动运维 → 自动化定时 → 资源优化 的完整闭环。 🎉