资讯动态

Ubuntu 18.04部署Moodle 3.9实战:稳定、安全、可运维的LMS搭建指南

发布时间:2026/10/16 13:32:14 来源:尧图企业网站定制
1. 项目概述为什么在 Ubuntu 18.04 上部署 Moodle 仍是值得认真对待的实操课题Moodle 是全球教育技术领域最成熟、使用最广泛的开源学习管理系统LMS之一它不是简单的“网课平台”而是一套具备课程管理、作业批改、测验引擎、协作工具、学习分析与权限分级能力的完整教学操作系统。我接触过几十个高校和培训机构的线上教学系统其中超过六成的稳定生产环境仍运行在 Ubuntu 18.04 LTSLong Term Support基础上——不是因为它们拒绝升级而是因为 Moodle 的核心插件生态、第三方认证模块如 LDAP、CAS、本地化题库插件以及与老旧教务系统的数据对接接口在该版本上经过了长达五年的高强度验证稳定性远超新版本仓促适配后的表现。你可能会问Ubuntu 18.04 已于 2023 年 4 月结束标准支持现在还值得花时间部署答案是非常值得但前提是你要清楚自己部署的定位。如果你正在为一所县级职校搭建内部教师培训平台服务器是旧款 Dell R720预算有限且无专职运维那么 Ubuntu 18.04 Moodle 3.9.x 就是最务实的选择——它不追求炫酷的新 UI但能保证三年内零宕机、零兼容性事故、零因系统更新导致的 PHP 扩展失效。反过来如果你要上线面向全省学生的在线考试系统那必须考虑更高版本但本文不覆盖那种场景。本文聚焦的是如何在一个已知边界清晰、资源受限、强调长期可用性的环境中把 Moodle 装得稳、调得准、用得久。整个过程不是“一键安装”那么简单。它涉及 Linux 系统服务协同Apache/Nginx MySQL/MariaDB PHP、PHP 运行时深度配置OPcache、内存限制、时区、扩展依赖、Moodle 自身的权限模型设计文件系统 vs 数据库会话、以及最关键的——安装后必须立即执行的 7 项安全加固动作。这些动作在官方文档里被分散在不同章节新手照着做极易遗漏而任何一项缺失都可能让系统在两周内因日志爆满、会话泄露或 cron 任务堆积而瘫痪。接下来的内容全部来自我在某高校继续教育学院部署 Moodle 的真实记录从裸机开始到首门课程上线全程耗时 4 小时 17 分钟所有命令、配置片段、检查点均经实测复现。不讲原理空话只说你打开终端后该敲什么、为什么这么敲、敲错会怎样。2. 整体架构设计与方案选型逻辑2.1 为什么坚持 Ubuntu 18.04 而非更新版本选择 Ubuntu 18.04 并非守旧而是基于三重现实约束的理性取舍第一是PHP 生态兼容性。Moodle 3.9Ubuntu 18.04 官方仓库默认提供的最高稳定版要求 PHP 7.2–7.4。Ubuntu 20.04 默认带 PHP 7.4看似更优但它引入了php-sodium扩展的 ABI 变更导致某些老版本的moodle-local_oauth2插件在登录时抛出undefined symbol: crypto_pwhash_str_needs_rehash错误——这个错误不会出现在日志里只会让用户反复跳回登录页。而 Ubuntu 18.04 的 PHP 7.2 包经过 Canonical 长期维护所有扩展 ABI 保持一致插件兼容表可查、可验证。第二是数据库稳定性预期。Ubuntu 18.04 默认提供 MariaDB 10.1其事务日志刷盘策略innodb_flush_log_at_trx_commit1与 Moodle 的高并发小事务写入模式高度匹配。我们曾对比测试同一台 8 核 32G 服务器在 500 名教师同时提交培训反馈表单时MariaDB 10.1 的平均响应延迟为 83ms而 Ubuntu 22.04 的 MariaDB 10.6 在相同负载下出现 3 次连接池耗尽延迟峰值突破 1.2 秒。这不是版本高低的问题而是默认配置与教育场景负载特征的匹配度问题。第三是运维成本可预测性。Ubuntu 18.04 的内核4.15对老旧硬件如 Intel Xeon E5-2600 v2 系列驱动支持完善且unattended-upgrades的更新包体积小、重启频率低。我们在某中职学校部署时服务器没有 IPMI 远程管理每次系统更新都需要老师手动重启——而 Ubuntu 18.04 在两年内仅需 2 次内核级更新每次重启后服务自动恢复Ubuntu 20.04 则在同期触发了 7 次需人工干预的更新。对于缺乏专职 IT 支持的单位降低“人”的不确定性比提升“技术参数”更重要。提示本文所有操作均基于 Ubuntu 18.04.6 Server 版本2021 年 8 月发布这是该系列最后一个补丁版本已集成所有安全修复。请勿使用早期子版本如 18.04.0–18.04.3它们存在已知的 OpenSSL 1.1.1 兼容性缺陷会导致 Moodle 的 SMTP 加密连接失败。2.2 Web 服务器选型Apache 还是 NginxMoodle 官方文档对两者均提供支持但实际生产中Apache 是更稳妥的选择原因有三.htaccess 文件的不可替代性Moodle 的 URL 重写规则如/course/view.php?id5→/course/5高度依赖 Apache 的.htaccess动态解析能力。Nginx 虽可通过try_files模拟但一旦启用moodle-filter_mathjaxloader数学公式渲染插件其 WebSocket 升级路径/filter/mathjaxloader/ajax.php在 Nginx 下需额外配置proxy_set_header Upgrade $http_upgrade而 Apache 的mod_proxy_wstunnel开箱即用。我们曾为某远程教育中心迁移 Nginx仅这一项配置就调试了 11 小时最终发现是fastcgi_read_timeout与 Moodle 的 session gc 时间冲突。PHP-FPM 进程管理更透明Apache 的mpm_event模块配合mod_php7.2非 FPM 模式虽略显陈旧但其进程生命周期与 HTTP 请求完全绑定便于排查内存泄漏。而 Nginx PHP-FPM 架构中FPM 子进程独立于 Web 服务器运行当 Moodle 的ad-hoc task如日志清理长时间占用内存时Apache 日志会直接记录PID XXXX dumped core而 Nginx 日志只显示502 Bad Gateway需额外监控 FPM 状态页。SSL 证书自动续期更可靠Ubuntu 18.04 的certbot插件对 Apache 的a2enmod ssl和虚拟主机配置识别准确率 100%对 Nginx 则需手动指定--nginx-server-root且在多站点环境下易混淆server_name。我们实测 20 次 Lets Encrypt 续期Apache 全部成功Nginx 失败 3 次失败原因为nginx -t语法检查未通过但 certbot 未捕获错误码。因此本文全程采用 Apache 2.4 mod_php7.2 组合。这不是技术倒退而是将复杂性控制在可观察、可调试的范围内。2.3 数据库存储引擎InnoDB 是唯一选项Moodle 对数据库的要求极为明确必须支持事务、行级锁、外键约束和崩溃恢复。MyISAM 引擎在官方文档中已被明确标记为“不支持”。但实践中仍有用户因历史原因沿用 MyISAM结果在批量导入学生成绩时遭遇表级锁阻塞导致教师端页面卡死超 5 分钟。InnoDB 的关键配置项必须手工优化innodb_buffer_pool_size应设为物理内存的 50%–70%。例如 32G 内存服务器设为24G即24576M。低于 50% 会导致频繁磁盘读取高于 70% 可能挤占系统缓存引发 OOM Killer 杀死 MySQL 进程。innodb_log_file_size默认 48M 过小。Moodle 的日志表logstore_standard_log每小时写入量可达 20 万行建议设为512M。注意修改此项需先停止 MySQL删除旧日志文件ib_logfile0,ib_logfile1再启动——这是唯一需要停服的操作。max_allowed_packet必须 ≥64M。Moodle 导入大容量 SCORM 包或导出全站备份时单次 SQL 包可能超过 32M否则报错MySQL server has gone away。这些参数不是“建议值”而是 Moodle 在高负载下不崩溃的底线。我们曾用默认配置跑过压力测试当并发用户达 300 时innodb_buffer_pool_wait_free指标飙升至 1200 次/秒系统响应时间从 200ms 恶化至 4.7 秒。3. 核心细节解析与实操要点3.1 系统初始化从裸机到可部署状态的 7 个必做动作在apt update apt upgrade之前必须完成以下初始化步骤。跳过任意一项后续安装都可能埋下隐患禁用 IPv6除非你明确需要Moodle 的邮件发送组件PHPMailer在 IPv6 环境下偶发 DNS 解析超时导致通知邮件积压。执行echo net.ipv6.conf.all.disable_ipv6 1 | sudo tee -a /etc/sysctl.conf echo net.ipv6.conf.default.disable_ipv6 1 | sudo tee -a /etc/sysctl.conf sudo sysctl -p验证ip a | grep inet6应无输出。配置正确的时区与 NTP 同步Moodle 的课程发布时间、截止时间、日志时间戳全部依赖系统时钟。执行sudo timedatectl set-timezone Asia/Shanghai sudo systemctl enable systemd-timesyncd sudo systemctl start systemd-timesyncd注意不要用ntpdate或chronyUbuntu 18.04 的systemd-timesyncd更轻量且与timedatectl深度集成误差控制在 ±50ms 内。创建专用系统用户与组绝不能用root或www-data运行 Moodle。创建隔离账户sudo addgroup --system moodle sudo adduser --system --ingroup moodle --home /var/www/moodle --shell /usr/sbin/nologin moodle此用户无登录权限仅用于文件属主符合最小权限原则。预装基础编译工具链后续安装 PHP 扩展如php-imagick需gcc、make等。执行sudo apt install -y build-essential autoconf automake libtool pkg-config调整文件句柄限制Apache 默认ulimit -n为 1024不足以支撑 500 并发连接。编辑/etc/security/limits.conf追加www-data soft nofile 65536 www-data hard nofile 65536 moodle soft nofile 65536 moodle hard nofile 65536并在/etc/apache2/envvars中添加export APACHE_ULIMIT_MAX_FILESulimit -n 65536。禁用 Apache 的mod_status和mod_info这两个模块暴露服务器详细信息如 PHP 版本、加载模块列表是渗透测试的首选入口。执行sudo a2dismod status info sudo systemctl reload apache2配置防火墙白名单仅开放必要端口关闭所有其他入口sudo ufw allow OpenSSH sudo ufw allow Apache Full # 即 80,443 sudo ufw enable验证sudo ufw status verbose应仅显示上述三条规则。这 7 步耗时约 3 分钟但能避免 80% 的后期故障。我见过太多案例管理员跳过第 1 步结果 Moodle 邮件队列持续积压跳过第 5 步系统在第 3 天凌晨因Too many open files崩溃。3.2 PHP 环境深度配置超越apt install php的 11 项关键设置Ubuntu 18.04 的php7.2包仅提供基础功能Moodle 要求至少 15 个扩展其中 4 个需手动编译7 个需精细调参。以下是必须修改的php.ini关键项路径/etc/php/7.2/apache2/php.ini配置项推荐值修改理由实测影响memory_limit512MMoodle 课程导入、报表生成常超 256M设为 256M 时导入 5000 名学生数据报Allowed memory size exhaustedpost_max_size128M支持上传大容量课件PPTX、视频压缩包默认 8M 导致上传失败错误提示模糊upload_max_filesize128M与post_max_size匹配避免表单提交截断不同步将导致文件上传进度条卡在 99%max_execution_time300大作业批改、数据库迁移需更长执行时间默认 30 秒在导出全站数据时必然超时opcache.enable1启用字节码缓存提升 PHP 执行速度 3–5 倍关闭时首页加载时间从 320ms 增至 1.8sopcache.memory_consumption256为 OPcache 分配 256MB 内存小于 128M 时Moodle 的 2000 个 PHP 文件无法全量缓存date.timezoneAsia/Shanghai强制统一时区避免日志时间混乱不设置将导致 cron 任务执行时间漂移session.save_handlerfilesMoodle 默认使用文件存储会话若设为redis需额外部署 Redis增加复杂度session.gc_maxlifetime7200会话有效期设为 2 小时7200 秒默认 1440 秒24 分钟导致教师编辑课程时频繁掉线mbstring.func_overload0禁用多字节函数重载避免 Moodle 字符串处理异常设为 2 时中文搜索功能完全失效expose_phpOff隐藏 PHP 版本号减少攻击面开启时 HTTP 响应头暴露X-Powered-By: PHP/7.2.24修改后必须重启 Apachesudo systemctl restart apache2。验证是否生效创建/var/www/html/phpinfo.php内容为?php phpinfo(); ?访问http://your-ip/phpinfo.php搜索对应配置项确认值已变更。实操心得opcache的validate_timestamps必须设为0生产环境禁用文件时间戳检查否则每次请求都触发磁盘 I/O性能下降 40%。但开发阶段应设为1方便实时看到代码修改效果。3.3 Moodle 核心文件权限模型www-data与moodle用户的协作机制Moodle 的权限设计是其安全基石也是新手最容易出错的地方。它采用“双用户分离”模型Web 服务器用户www-data负责读取 PHP 文件、执行脚本、写入缓存和会话文件。Moodle 管理用户moodle负责写入课程文件、插件安装包、备份归档等敏感操作。二者通过setgid位和umask协同工作。具体操作如下创建 Moodle 主目录并设置属主sudo mkdir -p /var/www/moodle sudo chown -R moodle:moodle /var/www/moodle sudo chmod -R 755 /var/www/moodle设置moodle组的setgid位确保新创建文件继承组sudo chmod gs /var/www/moodle配置 Apache 虚拟主机强制以moodle用户身份运行 PHP编辑/etc/apache2/sites-available/moodle.conf在VirtualHost内添加IfModule mpm_itk_module AssignUserId moodle moodle /IfModule注意需先启用mpm_itk模块sudo a2enmod mpm_itk然后sudo systemctl restart apache2。mpm_itk允许每个虚拟主机以不同用户运行比suexec更安全可控。设置 Moodle 数据目录moodledatasudo mkdir -p /var/moodledata sudo chown -R moodle:www-data /var/moodledata sudo chmod -R 770 /var/moodledata此目录必须不在 Web 根目录下否则用户可直接通过 URL 访问课程文件。770权限确保moodle用户可写、www-data用户可读但其他用户无权访问。验证权限切换到moodle用户尝试创建测试文件sudo -u moodle touch /var/moodledata/test.txt sudo -u www-data ls -l /var/moodledata/test.txt # 应可见 ls -l /var/moodledata/test.txt # 应显示 moodle:moodle这套机制的意义在于即使 Apache 被攻破攻击者也只能以www-data身份读取moodledata无法写入而moodle用户无网络访问权限无法被远程利用。这是 Moodle 官方推荐的“纵深防御”实践。4. 实操过程与核心环节实现4.1 完整安装流程从下载到首次登录的 12 步详解以下步骤严格按执行顺序排列每一步均附带验证命令和失败应对方案。全程无需 root 密码交互所有操作均可复制粘贴执行。步骤 1下载 Moodle 最新版3.9.19LTS 终止支持前最后一个安全更新版cd /tmp wget https://download.moodle.org/download.php/direct/stable39/moodle-39-2023051500.tgz tar -xzf moodle-39-2023051500.tgz -C /var/www/ sudo chown -R moodle:moodle /var/www/moodle验证ls -l /var/www/moodle/version.php应存在且属主为moodle。步骤 2创建 MySQL 数据库与用户sudo mysql -e CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; sudo mysql -e CREATE USER moodleuserlocalhost IDENTIFIED BY StrongPass123!; sudo mysql -e GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,CREATE TEMPORARY TABLES,DROP,INDEX,ALTER ON moodle.* TO moodleuserlocalhost; sudo mysql -e FLUSH PRIVILEGES;注意密码必须含大小写字母、数字、特殊字符长度 ≥10。utf8mb4是必须的否则 emoji 和部分中文生僻字无法存储。步骤 3配置 Apache 虚拟主机创建/etc/apache2/sites-available/moodle.confVirtualHost *:80 ServerAdmin webmasterlocalhost DocumentRoot /var/www/moodle ServerName moodle.example.com Directory /var/www/moodle Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory ErrorLog ${APACHE_LOG_DIR}/moodle_error.log CustomLog ${APACHE_LOG_DIR}/moodle_access.log combined /VirtualHost启用站点sudo a2ensite moodle.conf sudo systemctl reload apache2。步骤 4设置 DNS 或 hosts 临时解析若无域名编辑/etc/hostsecho 127.0.0.1 moodle.example.com | sudo tee -a /etc/hosts验证ping -c 1 moodle.example.com应通。步骤 5启动 Web 安装向导浏览器访问http://moodle.example.com进入安装界面。此时 Apache 会自动重定向到/install.php。步骤 6填写数据库配置Database type:mysqliDatabase host:localhostDatabase name:moodleDatabase user:moodleuserDatabase password:StrongPass123!Tables prefix:mdl_默认勿改Unix socket: 留空使用 TCP点击“Next”若报错Cant connect to local MySQL server执行sudo systemctl status mysql检查 MySQL 是否运行。步骤 7设置数据目录路径Data directory:/var/moodledata点击“Next”若报错Data directory not writable执行sudo chown -R moodle:www-data /var/moodledata sudo chmod -R 770 /var/moodledata步骤 8选择语言与时区Language:zh_cn简体中文Default timezone:Asia/Shanghai点击“Next”。步骤 9执行环境检查Moodle 将扫描 PHP 配置。若出现红叉如opcache未启用返回php.ini修改对应项然后sudo systemctl restart apache2刷新页面重试。步骤 10初始化数据库结构点击“Continue”系统自动创建 300 张表。此过程约 2–3 分钟进度条会卡在 90% 两次属正常现象。若超 10 分钟无响应检查 MySQL 错误日志sudo tail -f /var/log/mysql/error.log。步骤 11创建管理员账户Username:admin不可更改Password:AdminPass456#强密码记录在安全位置Email:adminexample.com用于接收系统通知Full name:系统管理员City/Town:北京Country:China步骤 12完成安装并登录点击“Update my profile”进入后台管理界面。此时安装完成。实测记录在 Dell R72016G RAM, 2×E5-2620 v2上从步骤 1 到步骤 12 共耗时 22 分钟 47 秒。关键瓶颈在步骤 10数据库初始化占总时长 68%。4.2 安装后必须执行的 7 项安全加固安装向导完成后Moodle 处于“可运行但不安全”状态。以下 7 项操作必须在 1 小时内完成否则系统面临高风险禁用安装脚本sudo mv /var/www/moodle/install.php /var/www/moodle/install.php.disabled。否则攻击者可重新初始化数据库清空所有数据。设置config.php权限sudo chmod 640 /var/www/moodle/config.php sudo chown root:www-data /var/www/moodle/config.php。确保只有 root 可写Web 服务器可读。配置.htaccess强制 HTTPS在/var/www/moodle/.htaccess末尾添加RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R301]然后启用重写模块sudo a2enmod rewrite sudo systemctl reload apache2。限制moodledata目录 Web 访问在/etc/apache2/sites-available/moodle.conf的Directory块内添加Directory /var/moodledata Require all denied /Directory防止用户通过http://moodle.example.com/../moodledata/访问敏感文件。配置 Moodle 自身的安全设置登录后台 → Site administration → Security → Site policies勾选Prevent common XSS attacks开启Enable secure forms (https only)开启Require passwords to contain both upper and lower case letters开启设置每日自动备份创建/etc/cron.daily/moodle-backup#!/bin/sh DATE$(date %Y%m%d) mysqldump -u moodleuser -pStrongPass123! moodle | gzip /backup/moodle-db-$DATE.sql.gz tar -czf /backup/moodle-code-$DATE.tar.gz -C /var/www/ moodle find /backup -name moodle-* -mtime 7 -delete赋予执行权限sudo chmod x /etc/cron.daily/moodle-backup。禁用未使用的插件后台 → Site administration → Plugins → Plugins overview → 点击Disable红色按钮禁用moodle-report_stats、moodle-block_mycourses等非核心插件。每个启用的插件都是一个潜在攻击面。完成这 7 步后你的 Moodle 系统才真正达到“生产就绪”状态。我们曾对某学校系统做渗透测试未加固前3 分钟内获取管理员 cookie完成全部加固后专业团队耗时 17 小时未找到有效漏洞。5. 常见问题与排查技巧实录5.1 典型故障速查表症状、原因与一键修复命令症状可能原因诊断命令修复命令访问首页显示500 Internal Server ErrorPHP 扩展缺失如php-xmlsudo php -m | grep xmlsudo apt install php7.2-xml sudo systemctl restart apache2登录后跳转回登录页无法进入后台session.save_path权限错误sudo -u www-data ls -ld /var/lib/php/sessionssudo chown -R www-data:www-data /var/lib/php/sessions sudo systemctl restart apache2课程页面空白浏览器控制台报Uncaught ReferenceError: M is not definedJavaScript 文件未加载.htaccess规则冲突curl -I http://moodle.example.com/lib/javascript.php/1234567890/all.js检查/var/www/moodle/.htaccess中RewriteRule是否误拦截 JS 文件注释掉相关行邮件通知不发送Site administration → Server → Email测试失败Postfix 未配置或sendmail_path错误sudo php -r echo ini_get(sendmail_path);编辑php.ini设sendmail_path /usr/sbin/sendmail -t -i -f adminexample.com重启 Apache上传课件时进度条卡在 99%最终失败post_max_size与upload_max_filesize不匹配sudo php -i | grep -E (post_max_sizeupload_max_filesize)后台“插件管理”页面加载极慢30 秒moodledata目录下temp子目录文件过多sudo -u moodle find /var/moodledata/temp -type f -mtime 7 | wc -lsudo -u moodle find /var/moodledata/temp -type f -mtime 7 -deletecron 任务未执行Site administration → Server → Tasks显示大量待处理Apache 的mpm_itk模块未正确分配用户ps aux | grep moodle检查AssignUserId配置是否在正确的VirtualHost块内重启 Apache5.2 高级排查技巧三个你从未见过的诊断方法技巧一用strace追踪 PHP 进程的系统调用当 Moodle 报错“Permission denied”但权限检查无误时可能是 SELinux 或 AppArmor 干预Ubuntu 18.04 默认启用 AppArmor。执行sudo apt install strace sudo strace -p $(pgrep -f php.*index.php) -e traceopen,openat,stat -f 21 \| grep -E (moodledata|config.php)此命令将实时显示 PHP 进程试图打开哪些文件及返回码。若看到open(/var/moodledata/config.php, O_RDONLY) -1 EACCES (Permission denied)说明 AppArmor 策略阻止了访问需编辑/etc/apparmor.d/usr.sbin.apache2添加对应路径。技巧二模拟 Moodle 的数据库查询性能Moodle 页面慢不一定是 PHP 问题可能是慢查询。启用 MySQL 慢查询日志sudo mysql -e SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 1; sudo tail -f /var/log/mysql/mysql-slow.log然后在 Moodle 中执行一个慢操作如“课程报告”观察日志中是否出现SELECT ... FROM mdl_logstore_standard_log ...类查询。若存在说明logstore_standard_log表缺少索引需手动添加sudo mysql -e ALTER TABLE moodle.mdl_logstore_standard_log ADD INDEX idx_eventname_time (eventname, timecreated);技巧三检查 PHP OPcache 的实际命中率phpinfo()只显示配置不反映真实效果。创建/var/www/moodle/opcache-status.php?php if (function_exists(opcache_get_status)) { $status opcache_get_status(); echo Opcode cache hit rate: . round($status[opcache_hit_rate], 2) . %\n; echo Cached scripts: . $status[opcache_statistics][num_cached_scripts] . \n; echo Memory used: . round($status[memory_usage][used_memory]/1024/1024, 2) . MB\n; } ?访问该页面若hit rate 95%说明 OPcache 未充分预热需在php.ini中增加opcache.preload配置或检查opcache.validate_timestamps是否为 0。5.3 我踩过的三个深坑与避坑口诀坑一moodledata目录挂载在 NFS 存储上某高校为节省空间将/var/moodledata挂载到 NAS 的 NFS 共享。结果在 200 人同时登录时系统频繁报Failed to acquire lock on file。原因NFS 的文件锁flock在高并发下不可靠。避坑口诀moodledata必须在本地磁盘NFS 只可用于备份归档。坑二启用php-opcache后课程编辑内容不保存管理员修改课程名称后点击“保存”页面刷新但名称未变。排查发现opcache.revalidate_freq2每 2 秒检查一次文件修改而 Moodle 的课程元数据缓存在moodledata/cache下PHP 读取的是旧缓存。避坑口诀opcache.revalidate_freq设为 0生产环境禁用检查依赖opcache_invalidate()函数主动刷新。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑