和上次发布,又多了几本电子书。
下面重要分享过程中遇到的问题和解决方案
1. LaTeX 公式渲染问题
问题描述: Markdown 中的 LaTeX 公式无法渲染。
诊断与解决:
- 初步判断: Markdown 渲染器默认不支持 LaTeX,或前端缺乏相应的数学渲染库。
- 后端处理: 在 Flask 应用的
app.py
中,修改read_chapter
路由的 Markdown 解析部分,引入pymdownx.arithmatex
扩展。该扩展负责将 Markdown 中的$inline$
和$$display$$
LaTeX 语法转换为前端库可识别的 HTML 结构(例如带有特定 class 的<span>
或<div>
)。- 关键配置:
extensions=['pymdownx.arithmatex']
和extension_configs={'pymdownx.arithmatex': {'generic': True}}
。
- 关键配置:
- 前端渲染: 在
templates/base.html
模板文件的<head>
部分,引入 MathJax 库(通过 CDN)。MathJax 是一个 JavaScript 库,它会在浏览器中解析由pymdownx.arithmatex
生成的 HTML 结构,并将其渲染为漂亮的数学公式。- 关键配置: MathJax 的 CDN 脚本
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
和 MathJax 配置MathJax = {...}
,特别是tex.inlineMath
和tex.displayMath
来定义 LaTeX 分隔符。
- 关键配置: MathJax 的 CDN 脚本
- 支持
math
/latex
代码块: 为支持math` 和
latex这种特殊的围栏代码块来书写数学公式,进一步在
app.py的
pymdownx.superfences扩展配置中,添加了自定义围栏条目:
{‘name’: ‘math’, ‘class’: ‘arithmatex’, ‘format’: fence_code_format}和类似的
latex条目。这使得这些代码块也能被
pymdownx.arithmatex` 处理。
2. MathJax 报错 TypeError: doc.childNodes is not iterable
问题描述: 在解决了 LaTeX 渲染问题后,控制台出现 Uncaught (in promise) TypeError: doc.childNodes is not iterable
错误,指向 MathJax 的 renderActions
。
诊断与解决:
- 原因分析: MathJax 3.x 版本对于
renderActions
的处理方式与旧版本不同,用户自定义的findScript
renderActions
与其内部机制冲突,导致在尝试遍历doc.childNodes
时出错。 - 解决方案: 在
templates/base.html
中,将 MathJax 配置中的options.renderActions
部分移除或注释掉。MathJax 3.x 核心通常会自动化处理这些配置,不需要手动干预。
3. ModuleNotFoundError: No module named 'streamlit_gsheets'
问题描述: 运行 Flask 应用时,出现 ModuleNotFoundError
,指示找不到 streamlit_gsheets
模块。错误堆栈显示这个导入发生在 pymdownx/__init__.py
内部。
诊断与解决:
- 原因分析:
pymdownx
(Pymdown Extensions) 是一个 Markdown 扩展库,它不应该依赖于streamlit_gsheets
。这极有可能是pymdown-extensions
的安装被损坏、被篡改或存在非官方版本导致的环境污染。 - 解决方案: 强制重新安装
pymdown-extensions
。pip uninstall pymdown-extensions
pip install pymdown-extensions
这确保了安装的是官方、干净的pymdown-extensions
版本,从而移除了不应该存在的streamlit_gsheets
依赖。
另外在新环境部署时,注意区分freeze和pipreqs ./ --encoding=utf-8对依赖包的管理,这样就可以避免很多依赖包的诡异问题
4. Nginx 静态目录图片无法访问 (Permission denied
)
问题描述: 部署到服务器后,静态目录下的图片(如 default_cover.png
和特定书籍封面)无法通过 https://dabuside.top/static/...
访问,Nginx 错误日志显示 Permission denied
。
诊断与解决:
- 初步判断: 服务器上的 Nginx 没有权限读取静态文件。这通常是因为 Nginx 的
location /static/
配置的root
或alias
指令不正确,或者文件/目录权限设置不当。 - 服务器部署特性: 在生产环境中,Nginx 负责直接服务静态文件,不应将
/static/
请求转发给 Flask 应用。 - 诊断方法与关键信息获取:
- 检查 Nginx 错误日志:
- 命令:
sudo tail -n 50 /var/log/nginx/error.log
或sudo journalctl -u nginx -n 50
- 目的: 确认错误信息是否为
Permission denied
,以及具体的文件路径。这是我们最初定位问题的重要线索。
- 命令:
- 确认 Nginx 运行的用户:
- 命令:
ps aux | grep "nginx: master process" | awk '{print $1}'
- 目的: 确定 Nginx 进程是以哪个系统用户身份运行的(例如
nginx
或www-data
)。这个用户必须拥有读取静态文件的权限。
- 命令:
- 检查 Nginx 配置文件:
- 命令:
sudo cat /etc/nginx/sites-enabled/your_domain.conf
(替换为实际配置文件路径) - 目的: 确认
location /static/
块中的root
指令是否正确指向 Flask 项目的根目录(即static
文件夹的父目录)。例如,如果静态文件在/home/xiaochengxu/flask-book-reader/static/
,则root
应为/home/xiaochengxu/flask-book-reader/
。
- 命令:
- 逐级检查目录权限(最关键):
- 命令:
ls -ld /home/ ls -ld /home/xiaochengxu/ ls -ld /home/xiaochengxu/flask-book-reader/ ls -ld /home/xiaochengxu/flask-book-reader/static/ ls -ld /home/xiaochengxu/flask-book-reader/static/covers/ ls -ld /home/xiaochengxu/flask-book-reader/static/covers/LLM/ ls -ld /home/xiaochengxu/flask-book-reader/static/covers/LLM/RAG/ ls -l /home/xiaochengxu/flask-book-reader/static/covers/LLM/RAG/cover.png
- 目的: 确认从根目录到目标文件路径中所有目录都对 Nginx 运行的用户拥有执行 (
x
) 权限。这是 Nginx 能够“穿越”这些目录以找到文件的必要条件。特别关注用户主目录 (/home/xiaochengxu/
) 的权限,它常常是权限链的断裂点。
- 命令:
- 检查 Nginx 错误日志:
- 根本原因定位: 根据日志和
ls -ld
输出,确认问题在于 Nginx 进程(以nginx
用户运行)没有权限进入到/home/xiaochengxu/
这个用户主目录,即使图片文件本身设置了nginx
用户可读。 - 最终解决方案:
- 调整目录所有权(可选,但推荐): 将 Flask 项目目录及其所有内容的组所有权更改为 Nginx 进程所属的组。
- 命令:
sudo chown -R xiaochengxu:nginx_group /home/xiaochengxu/flask-book-reader/
(将nginx_group
替换为 Nginx 运行用户所在的组,例如nginx
或www-data
)。
- 命令:
- 设置目录执行权限(核心): 确保从
/home/
到flask-book-reader/
目录路径中的所有目录(包括/home/xiaochengxu/
本身)都至少对 Nginx 用户(或其所属的组)拥有执行 (x
) 权限。- 命令:
sudo chmod 755 /home/xiaochengxu/
(如果主目录权限过严,确保 Nginx 可以进入)。 - 命令:
sudo find /home/xiaochengxu/flask-book-reader/ -type d -exec chmod 755 {} \;
(确保项目内部所有子目录可进入)。
- 命令:
- 设置文件读取权限: 确保图片文件本身具有读取权限。
- 命令:
sudo find /home/xiaochengxu/flask-book-reader/ -type f -exec chmod 644 {} \;
- 命令:
- 测试 Nginx 配置并重新加载:
- 命令:
sudo nginx -t
(测试配置语法) - 命令:
sudo systemctl reload nginx
(或sudo service nginx reload
) - 目的: 确保 Nginx 加载了新的权限设置。
- 命令:
- 调整目录所有权(可选,但推荐): 将 Flask 项目目录及其所有内容的组所有权更改为 Nginx 进程所属的组。
最佳实践补充: 强调将 Web 项目部署到 /var/www/
等标准 Web 服务器目录可以规避此类权限问题的优势,因为这些目录默认权限通常更适合 Web 服务。
整个过程涉及了后端 Python 配置、前端 JavaScript 库集成、以及 Linux 服务器文件系统权限与 Nginx Web 服务器配置的综合调试,最终成功解决了所有问题,使 Flask 阅读器能够正常运行并显示所有内容。