news 2026/10/5 13:19:15

Red Hat Linux 9上搭建Moodle:LAMP环境配置与SELinux实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Red Hat Linux 9上搭建Moodle:LAMP环境配置与SELinux实战指南

简介:一份PDF文档整理了在Red Hat Linux 9系统上搭建Moodle平台的完整实施方案,面向教育技术工作者、Linux系统管理员以及需要低成本建设在线教学环境的机构和个人教师。资源包内文件数为1,类型为PDF,大小约223KB,便于下载后直接阅读或保存备查,目前已有164人学习下载。内容从硬件兼容性说明入手,以一台具备1.8GHz主频CPU和256MB内存的普通办公电脑为例,覆盖磁盘分区、定制安装、卸载低版本组件、选配LAMP软件包、配置Apache与MySQL以及完成Moodle初始化等关键环节,同时还包括了数据库用户授权、站点目录权限设置等部署细节。特别是针对Red Hat Linux 9默认软件版本过低、与Moodle 1.9.x不兼容的问题,文档给出了明确的版本选型和安装顺序,并说明了libxml2、Compress-Zlib等库文件的用途,能够帮助读者规避部署中常见的坑,对依赖关系、权限要求与版本陷阱也进行了说明;资源还提供了从服务器环境搭建到课程管理平台上线运行的整体思路,适合作为教学部署的参考文献和专业指导;整体内容紧凑但步骤完整,适合按图索骥地复现,从系统安装到服务上线,文档对每一步的注意事项均有说明,尤其适合初次尝试在Linux环境中部署Moodle的读者。

1. 拿到这份 PDF 之前,先搞懂 Red Hat Linux 9 上搭 Moodle 到底难在哪

去年帮一所职校搭在线学习平台,运维手里就一份《基于Red Hat Linux 9的Moodle平台搭建.pdf》。看标题以为 Moodle 是主角,实际真正花时间的是 Red Hat Linux 9 的 SELinux、防火墙和软件源配置。Moodle 本身只是个 PHP 应用,安装向导相当成熟,但放到 RHEL 9 这种默认安全基线很硬的操作系统上,“能跑”和“稳定跑”之间隔着不少系统级设置。如果你是系统管理员,或者想在校内服务器上快速跑起一个有课程、作业、测验的在线教学平台,这篇就是把那个 PDF 里的信息重新落到命令行,让你一步步照着做。

2. 先定架构再动手:RHEL 9 上为什么选 LAMP 而不是 LNMP 或 OpenStack

2.1 版本选型:Red Hat Linux 9 与 Moodle 的兼容线

Red Hat Linux 9 也就是 RHEL 9,AppStream 仓库里默认带的软件版本其实非常“合适”:Apache 2.4.37+、MariaDB 10.5、PHP 8.0。Moodle 4.1 LTS 官方支持 PHP 7.4 到 8.0,Moodle 4.2 之后要求 PHP 8.0 以上。也就是说,直接用 RHEL 9 自带的 PHP 8.0 和 MariaDB 10.5,不必额外折腾第三方软件源,就能满足 Moodle 4.1 或 4.2 的安装要求。

这一点是很多人容易翻车的地方:看到新版本就想去装 PHP 8.1、8.2,或者把 MariaDB 升到 11.x,结果操作系统自带依赖和 Moodle 的插件生态反而出现兼容问题。我的习惯是:先跑dnf module list php看 AppStream 里有哪些 PHP 模块,再决定是否启用特定版本流。如果你手头就是给学校部署,稳定比激进重要得多。

2.2 用 LAMP 的理由:Apache、MariaDB、PHP 的匹配关系

不是所有场景都要一上来搞 openstack 云平台搭建,单节点的 Moodle 平台用经典 LAMP 就够。常见做法是 Apache + MariaDB + PHP,而不是 LNMP。原因很直接:Moodle 的插件和主题大量依赖.htaccess做目录级配置,Apache 原生支持.htaccess,Nginx 却需要你在 server 块里手工维护一份等价规则。用 Nginx 不是不行,但每装一个插件都可能要回头改 Nginx 配置,维护成本高。

MariaDB 选型也是同理:RHEL 9 仓库里自带的就是 MariaDB 10.5,和 Moodle 官方文档测试过的 MySQL 8.0 / MariaDB 10.x 是同一代。你要注意的只有字符集:建库时必须用utf8mb4,否则后面做课程讨论区时中文字符会乱。PHP 这边,Moodle 需要php-mysqlnd、php-xml、php-intl、php-mbstring、php-curl、php-zip、php-gd、php-opcache这些扩展。缺一个,安装向导的“环境检查”就会卡住,所以我在第 3 章会把整个安装命令一次给全。

2.3 第一次敲命令前:主机名、时间同步、防火墙与 SELinux

RHEL 9 默认开启 firewalld 和 SELinux enforcing,这是和 Debian/Ubuntu 最大的区别。很多人用惯 CentOS 7 就顺手把 SELinux 关掉,但这是给自己埋雷:后续升级或合规检查会很难看。正确做法是保持 SELinux 开启,只改 Moodle 相关目录的上下文。

开始安装之前,我会先做四件事。第一,更新系统并清理旧内核,避免安装完软件才发现依赖冲突。第二,设置一个稳定的主机名,因为 Moodle 的$CFG->wwwroot会用它来决定访问地址。第三,用 chrony 做时间同步,Moodle 的日志和 cron 都对时间敏感,时间差太大会导致任务重复执行或会话失效。第四,放行 HTTP/HTTPS 服务,不然你后面浏览器怎么都连不上。

# 1. 更新系统,建议先 reboot 一次再继续 sudo dnf update -y # 2. 设置主机名,后续 Moodle 会用它拼 URL sudo hostnamectl set-hostname moodle.example.com # 3. 安装并启动时间同步服务 sudo dnf install -y chrony sudo systemctl enable --now chronyd sudo timedatectl set-timezone Asia/Shanghai # 4. 放行 http 和 https,同时验证防火墙状态 sudo firewall-cmd --permanent --add-service=http --add-service=https sudo firewall-cmd --reload sudo firewall-cmd --list-all

这里第 4 步里--permanent表示规则会保存到重启之后,--reload让当前运行配置立即生效。--list-all用来确认你的 http/https 已经在 allowed-services 列表里。如果你是在虚拟化环境里测,还要同步看宿主机的安全组或网络策略,别只守着虚拟机防火墙。

SELinux 这边,我建议先不要做任何修改,等到第 5 章遇到具体权限报错时再对症处理。你只需要知道一个命令用来检查当前状态:

getenforce

输出是Enforcing就说明 SELinux 在工作。Moodle 安装之后需要让 Apache 能连接 MariaDB,还需要让 Apache 能写 Moodle 数据目录,这些都需要专门的 SELinux 布尔值和文件上下文。现在先把这一点存在脑子里,后面会具体用到。

3. 安装核心组件:Apache、MariaDB、PHP 与扩展的一键配置

3.1 用 dnf 安装软件包与 PHP 扩展

RHEL 9 的软件包管理是 dnf,和 yum 用法几乎一样。我一般会一次性把 Apache、MariaDB、PHP 和所有 Moodle 需要的扩展装完,避免安装向导跑到一半再回头补包。这里也提醒一句:不要用dnf install -y php*这种通配符,版本和源容易混乱,按名字装最可控。

# 安装 Web 服务器、数据库和 PHP 主程序 sudo dnf install -y httpd mariadb-server php php-cli php-fpm # 安装 Moodle 要求的 PHP 扩展 sudo dnf install -y php-mysqlnd php-xml php-intl php-mbstring php-curl php-zip php-gd php-opcache php-json

为什么有php-fpm?在 RHEL 9 上,Apache 可以通过mod_php直接执行 PHP,但如果你后面想调性能,让 PHP-FPM 和 Apache 的mod_proxy_fcgi配合是更干净的方案。先把php-fpm装上,不冲突,也不影响前期跑通。

装完后顺手验证一下版本和扩展加载情况:

php -v php -m | grep -E 'mysqli|xml|intl|mbstring|curl|zip|gd|opcache'

php -m列出的是当前 PHP 已经加载的模块,如果grep结果里少了mysqli,那多半是php-mysqlnd没装到位。你可以用dnf list installed php-*再查一遍实际安装的包名。

3.2 初始化 MariaDB:建库、建账号、调字符集

MariaDB 装好后默认监听在 3306 端口,root 用户没有密码。第一步是启动服务并跑一遍安全脚本,设置 root 密码、删除匿名用户、禁止 root 远程登录。在校园网环境里,这些操作尤其重要,因为很多内网服务器之间的网络并不隔离。

# 启动 MariaDB 并设为开机自启 sudo systemctl enable --now mariadb # 安全初始化,按提示设置 root 密码,其他选项选 y sudo mysql_secure_installation

安全脚本跑完后,用 root 登录建库和建账号。我会专门建一个叫moodle的数据库账号,而不是让 Moodle 直接使用 root,这样即使 Moodle 被注入,数据库权限也被限制在单个库内。

# 登录数据库,这里会提示输入你刚设置的 root 密码 mysql -uroot -p # 进入 MySQL 命令行后执行以下 SQL CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'moodle'@'localhost' IDENTIFIED BY 'ChangeThisPass2024'; GRANT ALL PRIVILEGES ON moodle.* TO 'moodle'@'localhost'; FLUSH PRIVILEGES; EXIT;

字符集utf8mb4_unicode_ci是专门给 Moodle 用的。utf8mb4支持 emoji 和中文姓名符号,unicode_ci排序规则能正确处理中文。如果你在创建数据库时漏了DEFAULT CHARACTER SET,后面表建好再改字符集就要动很多张表,价格非常贵。这里宁可一开始就写对。

3.3 配置 Apache 虚拟主机与 PHP 常用参数

RHEL 9 的 Apache 默认监听 80 端口,网页根目录是/var/www/html。我不会直接把 Moodle 解压到 html 根目录,而是建立一个独立的虚拟主机,指向/var/www/html/moodle这个子目录。这样以后在同一台服务器上再跑别的 Web 应用也不冲突。

# 创建虚拟主机配置文件 sudo vim /etc/httpd/conf.d/moodle.conf

在文件里写入:

<VirtualHost *:80> ServerName moodle.example.com DocumentRoot /var/www/html/moodle <Directory /var/www/html/moodle> Options FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog /var/log/httpd/moodle-error.log CustomLog /var/log/httpd/moodle-access.log combined </VirtualHost>

关键参数说明:AllowOverride All允许 Moodle 目录下的.htaccess生效,这是前面选 Apache 的核心原因;Require all granted允许所有来源访问,如果你只给校内用,可以改成Require ip 192.168.1.0/24来限定网段。ServerName需要和章节 2.3 设置的主机名一致。

改完配置后重载 Apache:

sudo systemctl enable --now httpd sudo systemctl reload httpd

PHP 参数也需要调整。Moodle 默认要求memory_limit至少 128M,推荐 256M;上传文件建议 80M,不然老师传视频课件很容易失败。我通常直接修改/etc/php.ini:

sudo sed -i 's/^memory_limit = .*/memory_limit = 256M/' /etc/php.ini sudo sed -i 's/^max_execution_time = .*/max_execution_time = 300/' /etc/php.ini sudo sed -i 's/^post_max_size = .*/post_max_size = 80M/' /etc/php.ini sudo sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 80M/' /etc/php.ini sudo systemctl reload httpd

这里memory_limit是单个 PHP 进程能用的最大内存,Moodle 的课程备份、批量导入作业都会一次性占用大量内存,256M 是比较安全的起步值。max_execution_time限制一个脚本最多跑 300 秒,防止某些大数据量页面被中断。如果后面你发现备份大课程还是超时,可以再把这个值往上调。

4. 让 Moodle 跑起来:下载、安装向导与 cron 任务的三段式落地

4.1 下载并放置 Moodle 源码

Moodle 官方提供 tar.gz 包,下载后解压到 Apache 的根目录。推荐用 LTS 版本,而不是最新不稳定版,我在生产部署时固定用 4.1 LTS。下载前先确认服务器能不能访问 Moodle 官方站点。

# 下载 Moodle 4.1 稳定版 wget https://download.moodle.org/download.php/direct/stable401/moodle-4.1.16.tgz -O /tmp/moodle.tgz # 解压到 Web 根目录 sudo tar -xzf /tmp/moodle.tgz -C /var/www/html/ # 设置 Apache 用户拥有文件权限 sudo chown -R apache:apache /var/www/html/moodle

chown -R apache:apache是必须的。Apache 进程默认以apache用户运行,如果文件所有者是 root,Moodle 安装向导就没办法写入config.php。你可能会想:那不就把整个目录都给 apache 了吗?安全上是否稳妥?这是 Moodle 官方安装步骤的标准做法,因为 Moodle 运行期要写日志和临时文件,给apache用户是正常状态。

另外还要创建数据目录。Moodle 的数据目录不能放在 Web 根目录下,否则用户可以直接通过 URL 访问到课程上传的文件。常见的做法是放在/var/moodledata:

sudo mkdir -p /var/moodledata sudo chown apache:apache /var/moodledata sudo chmod 700 /var/moodledata

chmod 700表示只有属主才能访问,配合目录位置在 html 之外,几乎就堵住了外部访问路径。如果你用 SELinux enforcing,这一步后面还需要补上下文,第 5 章会讲。

4.2 浏览器安装向导中的关键选项

源码就位后,打开浏览器访问http://moodle.example.com/moodle,进入 Moodle 安装向导。这里很容易踩坑,尤其是对第一次搭的人。你需要准备以下信息:

  • 数据目录:/var/moodledata
  • 数据库驱动:选择MariaDB/MySQL或mysqli
  • 数据库主机:localhost,端口 3306
  • 数据库名称:moodle
  • 数据库用户名:moodle
  • 数据库密码:你在 3.2 创建的密码
  • 表前缀:默认mdl_即可,别乱改
  • 网站 URL:http://moodle.example.com/moodle或http://IP/moodle

这里最容易翻车的点:如果你用的是 IP 访问,那么wwwroot必须也填写 IP。否则安装完成后,Moodle 会固执地把所有页面跳转到你填写的域名,而你的 DNS 又没有解析,浏览器就会一直打不开。以后要换域名,不要直接在config.php改,需要用php admin/cli/cfg.php命令维护。

安装向导会自己检查 PHP 扩展、目录权限、数据库连接。如果每一步都绿色通过,就可以选择安装版本,然后等待数据库初始化。整个初始化可能持续几分钟,别中途关掉浏览器。

4.3 配置系统级 cron:一分钟一次

Moodle 的很多后台任务不是即时执行的,比如课程通知、作业截止提醒、日志清理,全靠 cron 定时触发。官方要求你配置一个每 1 分钟跑一次的计划任务。最简单的方法是用系统 crontab,并指定以apache用户的身份执行,确保生成的文件权限和 Web 一致。

# 为 apache 用户添加 cron 任务 sudo crontab -u apache -e

在打开的编辑器里加入这一行:

* * * * * /usr/bin/php /var/www/html/moodle/admin/cli/cron.php > /dev/null 2>&1

* * * * *表示每分钟执行一次。最后的重定向符让 cron 不产生垃圾邮件,否则系统会把你当前的 shell 塞满提示。如果你希望保留执行日志,可以把> /dev/null改成>> /var/log/moodle-cron.log 2>&1,出问题时方便排查。

验证 cron 是否生效很简单:手动跑一次,然后查数据库的 logstore 表是否有记录。手动执行命令:

sudo -u apache /usr/bin/php /var/www/html/moodle/admin/cli/cron.php

如果这条命令正常结束,说明脚本路径和 PHP 版本没问题。再等一两分钟,进入 Moodle 后台的“站点管理 > 系统报告 > 计划任务”,你会看到计划任务列表里有执行时间,不再是“从不”。

4.4 加固目录权限与 config.php

安装完成后,Moodle 会在数据目录里生成一个config.php备份,同时 Web 根目录下也有config.php。正常安装后根目录下的config.php已经生成,并且里面有数据库账号密码,需要把权限降到 644:

sudo chmod 644 /var/www/html/moodle/config.php sudo chown root:apache /var/www/html/moodle/config.php

chmod 644防止被其他用户修改,chown root:apache保证 Apache 能读取但只有 root 能写。别把 config.php 改成 777,那相当于把数据库密码贴在门上。

另外,在数据目录里,很多新手会把/var/moodledata设置成777,理由是安装向导一直报“写入失败”。这是典型的错误做法。报错往往不是权限位不够,而是 SELinux 没放行。保持700,后面用 SELinux 命令来解决才是正道。

5. Red Hat Linux 9 上搭 Moodle 的典型踩坑与排查记录

5.1 SELinux 拦截让数据目录无法写入

现象:安装向导在“目录权限检查”处报/var/moodledata不可写,提示你 chmod 777。你明明已经用chown apache:apache和chmod 700 -R,但页面依然红色失败。

原因:RHEL 9 的 SELinux enforcing 模式下,Apache 的进程域是httpd_t,默认只能写httpd_sys_rw_content_t类型的目录,普通目录类型default_t不在允许范围内。

解决:用semanage把数据目录默认上下文改成 Apache 可写类型。

# 安装管理工具 sudo dnf install -y policycoreutils-python-utils # 为数据目录添加 SELinux 文件上下文规则 sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/moodledata(/.*)?" sudo restorecon -Rv /var/moodledata

运行完再刷新安装页面,拒绝状态就消失了。另外还要开启 Apache 连数据库的布尔值:

sudo setsebool -P httpd_can_network_connect_db on

-P表示持久化,重启后依然生效。如果不开启,Moodle 安装到数据库连接阶段会报“无法连接数据库”,日志里看到Permission denied,但你的数据库用户名密码明明是对的。

5.2 PHP 扩展缺失导致环境检查不通过

现象:安装向导环境检查页列出intl、gd、zip、opcache等项目不满足,直接红叉。

原因:你只装了php基础包,没有安装 Moodle 需要的配套扩展。RHEL 9 的 php 包拆分很细,基础包只包含核心解释器。

解决:一次性安装齐全后重启 PHP 进程。

sudo dnf install -y php-intl php-gd php-zip php-opcache php-xml php-mbstring php-curl php-mysqlnd sudo systemctl reload httpd php -m | grep intl

注意如果是 PHP-FPM 架构,改完扩展后要systemctl restart php-fpm,而不是只 reload httpd。否则新扩展不会加载。

5.3 忘配 cron 导致站点静默变慢

现象:网站能打开,但课程报名后学生收不到通知,作业截止时间过了也没有提醒,后台日志一直有积压。

原因:Moodle 大量异步任务依赖 cron。没配 cron,队列就会不断堆积。安装向导最后一页只提示你不配会有问题,并不会阻止完成安装。

解决:按 4.3 配置 cron,并手动执行一次确认能跑通。执行后观察/var/moodledata下是否有新的临时日志文件,以及后台计划任务页面的“上次执行时间”是否跳动。这是个典型的“黑匣子”问题,不触发不会暴露,等学生开始抱怨就晚了。

5.4 防火墙没放行,浏览器一直转圈

现象:在同一台机器上用curl http://localhost/moodle能拿到页面,但在局域网另一台电脑上浏览器就是打不开。

原因:RHEL 9 默认 firewalld 只放行 ssh,80/443 端口需要显式添加。检查时应看防火墙和 SELinux 两层,但很多时候是防火墙这一层。

解决:

sudo firewall-cmd --permanent --add-service=http --add-service=https sudo firewall-cmd --reload sudo ss -ltnp | grep :80

ss -ltnp是看端口监听状态和进程,如果输出显示 httpd 监听 0.0.0.0:80,防火墙也放行了,仍然不通,这时候再查云主机的安全组或物理交换机的 ACL。网络层的坑往往是一层套一层,我一般会用telnet IP 80从外部测三层连通性。

5.5 MariaDB 字符集混乱导致中文字符乱码

现象:课程名称和用户姓名显示为“???”,或者数据表里能存中文但页面是乱码。

原因:创建数据库时没有指定utf8mb4,或者连接数据库的配置文件里强制了latin1。RHEL 9 的 MariaDB 默认字符集不一定就是 utf8mb4。

解决:确认当前库和表的字符集。

SHOW CREATE DATABASE moodle; SELECT default_character_set_name, default_collation_name FROM information_schema.SCHEMATA WHERE schema_name='moodle';

如果返回不是 utf8mb4,需要重建库或转换。生产环境我一般选择导出再重建,别直接用 ALTER 语句硬改列类型,容易遇到索引超长问题。具体步骤是mysqldump -u root -p --default-character-set=utf8mb4 moodle > moodle.sql,然后删除重建库,指定字符集后再导入。这一套操作在维护窗口做,别在高峰期搞。

6. 让它更可靠:HTTPS、Redis 缓存与命令行体检

安装能跑通只是第一步,真正能交给学校用还得补上 HTTPS、缓存和体检手段。我一般会在 Moodle 站点启用后的第二天做下面三件事。

先配 HTTPS。RHEL 9 自带的mod_ssl可以配自签名证书,但浏览器会有安全警告。如果学校有统一证书,直接把它放到/etc/pki/tls/certs/和/etc/pki/tls/private/,在虚拟主机里加一行:

<VirtualHost *:443> ServerName moodle.example.com DocumentRoot /var/www/html/moodle SSLEngine on SSLCertificateFile /etc/pki/tls/certs/moodle.crt SSLCertificateKeyFile /etc/pki/tls/private/moodle.key </VirtualHost>

然后开启 HTTP 跳转 HTTPS。Moodle 的$CFG->sslproxy和$CFG->wwwroot都要改成https://开头,否则页面加载一半 http 一半 https,登录状态会丢失。

再配 Redis 做会话和缓存。Moodle 默认用文件存缓存,并发稍微上来就扛不住。RHEL 9 装 Redis 很简单,但注意:SELinux 下 httpd 要能连接 Redis 端口,需要再跑一个布尔值。给config.php和 Redis 的配置,我会在config.php里加入:

$CFG->session_handler = 'redis'; $CFG->session_redis_host = '127.0.0.1'; $CFG->session_redis_port = 6379;

配置完用下面命令验证整站健康状态:

sudo -u apache php /var/www/html/moodle/admin/cli/check.php

这个命令会扫描所有目录、数据库、cron、缓存后端,输出一个个状态结果。只要出现OK字样的多,站点就基本安全。再配合tail -f /var/log/httpd/moodle-error.log盯上两天,有没有异常一目了然。

我自己踩过的最大坑就是装完就不管了,结果两个月后学生访问高峰直接把 Apache 进程打满,才发现 cron 停了、opcache 没开、数据目录没迁移到独立磁盘。后来养成一个习惯:每次部署完必跑一次check.php,把输出截图存档。这个动作省下来的排查时间,比做任何规划都多。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 13:06:18

Compressing Large Language Models with PCA Without Performance Loss

文章主要内容总结 本文探讨了通过结构化应用主成分分析(PCA)对大型神经网络模型进行极端压缩且不损失性能的方法。核心思路是:在训练前对输入数据进行PCA压缩,而非事后对模型进行修剪或简化,使模型容量与数据的内在信息含量相匹配,从而在多个模态(图像、文本分类、文本…

作者头像 李华
网站建设 2026/10/5 12:57:51

deali.II 入门教程:从网格生成到自适应细化,带你跑通 step-1

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 12:57:26

基于STM32与HX711的智能计价电子秤完整设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 12:55:47

LaTeX双栏论文跨栏图表乱跑?用dblfloatfix宏包根治浮动体错位

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华