1. 为什么在 Ubuntu 16.04 上部署 Moodle 仍是值得认真对待的实操课题
Moodle 是全球教育技术领域里真正经得起时间考验的开源学习管理系统(LMS),它不像某些昙花一现的在线教学工具,而是以高度可定制、权限体系严密、插件生态成熟著称。虽然 Ubuntu 16.04 已于 2021 年 4 月结束标准支持,但现实中大量中小型学校、培训机构、企业内训部门仍在使用基于该版本构建的稳定服务器环境——不是因为守旧,而是因为迁移成本高、现有课程资源与插件兼容性经过长期验证、运维团队对系统行为已形成肌肉记忆。我去年帮三所县级职校做数字化教学平台评估时,发现其中两所的 Moodle 实例仍跑在 Ubuntu 16.04 + Apache 2.4.18 + PHP 7.0 组合上,它们最常问的问题不是“怎么升级”,而是“怎么让新装的 H5P 插件不崩”、“怎么把旧版 SCORM 包导出的数据无缝迁入新服务器”。这说明,掌握一套在经典 LTS 版本上可靠部署 Moodle 的完整方法论,远比单纯追求最新版本更有现实价值。
核心关键词
Moodle、Ubuntu 16.04、Apache、MySQL、PHP
不是孤立的技术名词,而是一条紧密咬合的运行链路:Apache 是请求入口和静态资源分发器,PHP 是业务逻辑执行引擎,MySQL 是数据持久化中枢,Moodle 则是运行在这三者之上的应用层大脑。任何一个环节配置失当,都会导致登录页白屏、课程无法保存、用户权限错乱等典型故障。比如,很多人忽略 PHP 的
date.timezone
设置,结果 Moodle 日志里全是“PHP Warning: date(): It is not safe to rely on the system's timezone settings”,继而引发课程截止日期计算错误;又比如 MySQL 默认的
sql_mode
在 Ubuntu 16.04 的 mysql-server-5.7 包中启用了
STRICT_TRANS_TABLES
,而早期 Moodle 版本(如 3.1–3.3)的部分 SQL 语句未显式处理 NULL 值,直接导致安装向导卡在数据库连接测试环节。这些细节,官方文档往往一笔带过,但实际部署时就是拦路虎。本文要做的,不是照搬官网安装指南,而是把我在过去八年里,在 17 所不同机构部署 Moodle 所踩过的坑、验证过的参数、手写过的检查脚本,全部摊开来讲清楚。无论你是刚接触 Linux 的教务老师,还是需要快速交付项目的运维工程师,都能从中拿到可直接粘贴执行的命令、可立即复用的配置片段、以及最关键的——判断问题根源的思维路径。
2. 整体架构设计与技术选型背后的硬逻辑
2.1 为什么必须锁定 Ubuntu 16.04 的特定软件栈组合
Ubuntu 16.04 作为长期支持(LTS)版本,其软件仓库(main/universe)中的 Apache、MySQL、PHP 版本是经过 Canonical 官方严格测试并保证相互兼容的。我们绝不能为了“追新”而自行编译或从第三方 PPA 源安装更高版本,原因有三:
第一,
ABI 兼容性风险
。Ubuntu 16.04 默认的 Apache 是 2.4.18,其模块加载机制(尤其是 DSO 动态共享对象)与 PHP 的 apache2handler 模块深度绑定。如果你通过
apt-get install php
安装的是官方源的 PHP 7.0.33,那么
libapache2-mod-php7.0
包会自动完成
LoadModule php7_module /usr/lib/apache2/modules/libphp7.0.so
的注册,并在
/etc/apache2/mods-enabled/php7.0.load
中建立符号链接。但若你手动下载 PHP 7.4 的二进制包并尝试加载
libphp7.4.so
,Apache 启动时大概率报错
Cannot load /usr/lib/apache2/modules/libphp7.4.so into server: /usr/lib/apache2/modules/libphp7.4.so: undefined symbol: ap_log_error
——这是因为 Apache 2.4.18 的内部函数符号表与 PHP 7.4 编译时链接的 Apache 头文件版本不一致。我曾在一个客户现场花了两天排查这个错误,最后发现是运维同事偷偷替换了 PHP 版本。
第二,
安全更新通道唯一性
。Ubuntu 16.04 的官方安全公告(USN)只覆盖其仓库中提供的软件包。例如,MySQL 5.7.33-0ubuntu0.16.04.1 这个包号,意味着它是 Ubuntu 团队针对 CVE-2021-23017 等漏洞打过补丁的定制版本。如果你用 MySQL 官网的
.deb
包安装了 5.7.35,那么即使上游修复了某个漏洞,Ubuntu 的
apt update && apt upgrade
也不会为你更新它,你的系统就暴露在已知风险之下。教育类系统存储着大量学生个人信息,合规性是底线。
第三,
Moodle 官方认证的兼容矩阵
。查阅 Moodle 3.5(最后一个明确支持 Ubuntu 16.04 的主流版本)的系统需求文档,其明确列出的最低要求是:PHP 7.0.0+、MySQL 5.5.31+、Apache 2.2+。而 Ubuntu 16.04 仓库中
php7.0
、
mysql-server-5.7
、
apache2
三者的版本号恰好落在这个黄金交集内,且经过 Moodle QA 团队的交叉测试。这是经过千锤百炼的“稳态组合”,不是靠运气凑出来的。
2.2 Apache 配置的核心取舍:MPM 模块选择与 MPM Event 的致命陷阱
Apache 在 Ubuntu 16.04 上默认启用的是
prefork MPM
,而非更时髦的
event MPM
。这是一个关键但常被误解的设计点。Prefork 是多进程模型,每个请求由一个独立的子进程处理,内存占用高但稳定性极佳,尤其适合运行 PHP 这类非线程安全(ZTS disabled)的解释器。而 event MPM 是多线程模型,单个进程可并发处理多个请求,资源效率高,但它要求所有加载的模块(包括 PHP)都必须是线程安全的。Ubuntu 16.04 官方源的
php7.0
包编译时明确禁用了 ZTS(
--disable-zts
),这意味着它只能在 prefork 或 worker MPM 下安全运行,event MPM 会直接导致 Apache 崩溃或 PHP 变量随机丢失。
我见过太多人为了“性能”强行切换到 event,结果 Moodle 的论坛帖子内容莫名消失、测验分数提交后归零。这不是 Moodle 的 Bug,而是底层运行时环境的不匹配。因此,我们的 Apache 配置必须显式确认并加固 prefork 行为:
# 检查当前启用的 MPM
a2query -M
# 输出应为 'prefork'
# 查看 prefork 的核心参数
cat /etc/apache2/mods-available/mpm_prefork.conf
其中最关键的三个参数是:
-
StartServers: 启动时创建的子进程数。对于 Moodle 这类 I/O 密集型应用,设为5足够,避免冷启动延迟。 -
MinSpareServers/MaxSpareServers: 空闲进程池上下限。设为5和10,既能快速响应突发请求,又不会长期占用过多内存。 -
MaxRequestWorkers: 同一时刻能处理的最大并发请求数。这是内存规划的锚点。每个 Apache 子进程平均消耗约 20–30MB 内存(含 PHP 解释器)。若服务器有 2GB 内存,保守起见设为64(64 × 25MB ≈ 1.6GB),留出余量给 MySQL 和系统。
提示:不要盲目调高
MaxRequestWorkers。Moodle 的瓶颈通常不在 Apache 并发数,而在 MySQL 连接数和 PHP 的max_execution_time。盲目增加会导致 MySQL 连接耗尽(Too many connections错误),反而降低整体吞吐。
2.3 MySQL 配置的教育场景特化:不只是
innodb_buffer_pool_size
MySQL 在 Moodle 中承担着课程结构、用户状态、成绩记录等所有核心数据的存储。Ubuntu 16.04 的
mysql-server-5.7
默认配置是为通用场景优化的,但 Moodle 有其独特读写模式:高频小事务(如点击“标记为完成”)、大量 BLOB 字段(课件附件)、复杂的 JOIN 查询(如学生成绩报表)。因此,我们必须进行针对性调优。
首要任务是调整
innodb_buffer_pool_size
。这不是一个凭空猜测的值,而是有计算公式的:
推荐值 = 服务器总内存 × 0.7(对于专用 Moodle 数据库服务器)
例如,2GB 内存的服务器,应设为
1433600000
字节(即 1.4GB)。这个值确保了绝大多数 InnoDB 数据页能常驻内存,极大减少磁盘 I/O。设置方法是在
/etc/mysql/mysql.conf.d/mysqld.cnf
的
[mysqld]
段落下添加:
innodb_buffer_pool_size = 1433600000
但仅此一项远远不够。Moodle 的
mdl_logstore_standard_log
表(记录所有用户操作日志)会随时间疯狂增长,若不做清理,几个月后单表可达数十 GB,严重拖慢备份和查询。官方建议启用
logstore_standard
插件的日志保留策略,但更底层、更有效的做法是在 MySQL 层面启用
分区(Partitioning)
。虽然 Ubuntu 16.04 的 MySQL 5.7 默认支持分区,但需手动开启:
-- 登录 MySQL 后执行
SET GLOBAL innodb_file_per_table=ON;
SET GLOBAL innodb_file_format=Barracuda;
-- 然后对 mdl_logstore_standard_log 表按时间分区(需先备份)
不过,分区操作对生产库有风险,因此我们采用更稳妥的“冷热分离”策略:每月初用 cron 自动将上月日志归档到历史表,并清空主表。这需要一个简单的 Bash 脚本配合 MySQL 事件调度器,我会在实操环节给出完整代码。
另一个常被忽视的点是
max_allowed_packet
。Moodle 上传大课件(如 100MB 的视频压缩包)时,PHP 的
post_max_size
和
upload_max_filesize
只控制了 PHP 层,但 MySQL 接收
INSERT INTO mdl_files ... VALUES (...)
语句时,如果 BLOB 字段过大,会因超出
max_allowed_packet
而报错
Packet for query is too large
。因此,必须将此项设为至少
64M
,与 PHP 的上传限制对齐。
3. 核心细节解析与实操要点:从系统准备到 Moodle 初始化
3.1 系统级预检:绕过 Ubuntu 16.04 的“隐藏陷阱”
在敲下第一个
apt
命令前,必须完成三项关键预检,否则后续步骤可能在深夜崩溃:
第一,检查并修正系统时区与 NTP 同步。
Moodle 的所有时间戳(课程开始/结束、作业截止、日志记录)都依赖系统时间。Ubuntu 16.04 安装时若未联网,时区可能被设为
Etc/UTC
,而
date
命令显示的时间却是本地时间,造成巨大混淆。执行:
# 查看当前时区设置
timedatectl status | grep "Time zone"
# 若显示 "Etc/UTC" 但你期望是 "Asia/Shanghai",则修正:
sudo timedatectl set-timezone Asia/Shanghai
# 强制同步时间(需确保 ntp 服务已安装)
sudo systemctl restart systemd-timesyncd
sudo timedatectl set-ntp true
注意:
systemd-timesyncd是 Ubuntu 16.04 的默认 NTP 客户端,比老旧的ntpd更轻量。不要卸载它去装chrony,除非你有特殊需求。
第二,禁用 Ubuntu 的
apparmor
对 Apache 的过度限制。
AppArmor 是 Ubuntu 默认的安全模块,它为 Apache 进程定义了严格的文件访问策略。但 Moodle 的插件机制(尤其是
local/
目录下的自定义插件)常常需要 Apache 读取
/var/www/moodle/local/pluginname/
下的任意 PHP 文件,而默认的
/etc/apparmor.d/usr.sbin.apache2
策略并未包含此路径,导致 403 Forbidden 错误。最稳妥的解法不是粗暴禁用 AppArmor,而是为其添加规则:
# 编辑 Apache 的 AppArmor 配置
sudo nano /etc/apparmor.d/usr.sbin.apache2
# 在文件末尾的 "/usr/sbin/apache2" 配置块内,添加:
/var/www/moodle/** mr,
/var/www/moodle/local/** mr,
# 保存后重载策略
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.apache2
这条规则赋予 Apache 对 Moodle 主目录及其
local/
子目录的读取(r)和内存映射(m)权限,既满足功能需求,又不破坏整体安全边界。
第三,为 MySQL 创建专用的
moodle
用户并授予权限,而非使用
root
。
这是安全基线。执行以下 SQL(替换
your_strong_password
):
CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'moodle'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,CREATE TEMPORARY TABLES,DROP,INDEX,ALTER ON moodle.* TO 'moodle'@'localhost';
FLUSH PRIVILEGES;
关键点在于字符集
utf8mb4
。Ubuntu 16.04 的 MySQL 5.7 默认支持
utf8mb4
,它能完整存储 Emoji 和生僻汉字(如“𠮷”字),而旧的
utf8
实际上是
utf8mb3
,最多只支持 3 字节字符,会导致 Moodle 导入含 Emoji 的课程描述时出错。
COLLATE utf8mb4_unicode_ci
则确保中文排序和比较符合预期。
3.2 Apache 与 PHP 的协同配置:不止于
a2enmod
安装基础软件包是起点,但真正的难点在于让 Apache 和 PHP “说同一种语言”。以下是经过反复验证的最小可行配置:
# 1. 安装核心组件(一条命令,确保版本一致性)
sudo apt update && sudo apt install -y apache2 mysql-server php7.0 libapache2-mod-php7.0 php7.0-mysql php7.0-curl php7.0-xml php7.0-xmlrpc php7.0-soap php7.0-intl php7.0-mbstring php7.0-cli php7.0-zip
# 2. 启用必要模块
sudo a2enmod rewrite headers expires
# rewrite: Moodle URL 重写(如 /course/view.php?id=2 → /course/2)
# headers & expires: 为静态资源(CSS/JS/图片)设置缓存头,提升前端加载速度
# 3. 配置 PHP 核心参数(编辑 /etc/php/7.0/apache2/php.ini)
sudo nano /etc/php/7.0/apache2/php.ini
在
php.ini
中,必须修改以下关键项(搜索并取消注释,然后修改值):
; 将时区设为你的地区,避免 Moodle 时间错乱
date.timezone = Asia/Shanghai
; Moodle 大文件上传必需
upload_max_filesize = 128M
post_max_size = 128M
max_execution_time = 600
max_input_time = 600
memory_limit = 512M
; Moodle 安全必需
file_uploads = On
allow_url_fopen = Off
allow_url_include = Off
session.cookie_httponly = On
实操心得:
max_execution_time = 600(10分钟)是 Moodle 执行大型课程备份或恢复操作的底线。我曾遇到一个客户,其课程包含 2000 个测验题,恢复时默认的 30 秒超时导致操作永远失败。将此项设为 600 后,问题迎刃而解。但切记,这只是临时放宽,不能替代对慢查询的优化。
配置完 PHP,必须重启 Apache 使更改生效:
sudo systemctl restart apache2
验证 PHP 是否工作:在
/var/www/html/
下创建
info.php
:
<?php phpinfo(); ?>
然后在浏览器访问
http://your_server_ip/info.php
。重点检查:
-
Loaded Configuration File
: 应为
/etc/php/7.0/apache2/php.ini -
date.timezone
: 应显示
Asia/Shanghai -
Loaded Modules
: 应包含
mysqli,curl,xml,mbstring等
若页面空白或报错,90% 的原因是
libapache2-mod-php7.0
未正确加载。此时执行
sudo a2dismod mpm_event && sudo a2enmod mpm_prefork && sudo systemctl restart apache2
,强制回归安全的 prefork 模式。
3.3 Moodle 源码部署与权限固化:安全与可用性的平衡术
Moodle 官方提供两种获取方式:Git 克隆(适合开发者)和 ZIP 包下载(适合生产部署)。对于 Ubuntu 16.04 的生产环境,我强烈推荐后者,因为 ZIP 包是经过 QA 测试的稳定发布版,且不含开发用的
.git
目录,减少了潜在攻击面。
# 进入 Web 根目录
cd /var/www/
# 下载 Moodle 3.5.16(最后一个支持 Ubuntu 16.04 的 LTS 版本)
sudo wget https://download.moodle.org/download.php/direct/stable35/moodle-3516.zip
sudo unzip moodle-3516.zip
sudo chown -R www-data:www-data moodle
sudo chmod -R 755 moodle
这里
chown
和
chmod
的组合是精髓。
www-data
是 Ubuntu 下 Apache 的默认运行用户,Moodle 的所有文件必须属于它,否则 Apache 无法读取 PHP 文件,也无法向
moodledata
目录写入缓存、上传的文件等。
755
权限(所有者 rwx,组 rx,其他 rx)是安全与功能的平衡点:它允许 Apache 读取和执行,但禁止世界可写,防止恶意脚本注入。
接下来,创建 Moodle 的数据存储目录
moodledata
。
此目录绝不能放在
/var/www/moodle/
内!
这是 Moodle 安全白皮书反复强调的铁律。因为如果 Apache 配置失误,外部用户可能通过 URL 直接访问到
moodledata
下的敏感文件(如数据库备份、用户上传的私密文档)。正确做法是将其置于 Web 根目录之外:
sudo mkdir /var/moodledata
sudo chown www-data:www-data /var/moodledata
sudo chmod 750 /var/moodledata
750
权限(所有者 rwx,组 rx,其他 —)进一步收紧了访问控制,只有
www-data
用户及其所属组(通常是
www-data
组)才能访问。
最后,配置 Apache 的虚拟主机,将域名(如
moodle.school.edu
)指向 Moodle 目录。编辑
/etc/apache2/sites-available/moodle.conf
:
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName moodle.school.edu
DocumentRoot /var/www/moodle
<Directory /var/www/moodle>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# 关键:显式禁止访问 moodledata 目录
<Directory /var/moodledata>
Require all denied
</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
现在,访问
http://moodle.school.edu
,Moodle 的图形化安装向导就会出现。整个过程没有一行代码需要手写,所有命令均可复制粘贴,且每一步都对应一个明确的安全或功能目标。
4. 实操过程与核心环节实现:从安装向导到首门课程上线
4.1 Moodle 图形化安装向导的“通关秘籍”
Moodle 的安装向导(
/install.php
)看似简单,但几个关键选项的选择将决定未来数月的运维体验。以下是我在 17 个实例中总结出的“零失误”配置路径:
第一步:环境检查(Environment Check)
向导会自动检测 PHP、数据库、Web 服务器等。99% 的失败都发生在这里。若看到红色叉号,请按如下顺序排查:
-
PHP extensions missing
: 确保
php7.0-mysql、php7.0-xml等已安装(见 3.2 节)。 -
PHP setting 'date.timezone'
: 确保
php.ini中已设置(见 3.1 节)。 -
PHP setting 'opcache.enable'
: Ubuntu 16.04 的
php7.0-opcache默认已启用,无需额外操作。若显示未启用,执行sudo phpenmod opcache。
第二步:数据库设置(Database Settings)
-
Database type
: 选择
MySQLi(不是MySQL,后者已废弃)。 -
Database host
:
localhost(不要填127.0.0.1,虽然效果相同,但localhost会触发 Unix socket 连接,性能略优)。 -
Database name
:
moodle(与 3.1 节创建的数据库名一致)。 -
Database user
:
moodle(与 3.1 节创建的用户名一致)。 - Database password : 输入你在 3.1 节设定的密码。
-
Table prefix
: 保持默认
mdl_。修改前缀对安全性提升微乎其微,却会给后续的 SQL 直接查询带来麻烦。
第三步:网站设置(Website Settings)
-
Full website name
: 填写学校/机构全称,如
XX职业技术学院在线学习平台。 -
Short name
: 简称,如
XX职院,用于页面标题和导航栏。 - Administrator email : 填写管理员邮箱,Moodle 会用它发送系统通知。
-
Username
:
admin(这是超级管理员账号,务必牢记)。 - Password : 设置一个强密码(至少 12 位,含大小写字母、数字、符号)。
- First name / Surname : 填写管理员真实姓名,用于系统日志和通知署名。
第四步:完成安装(Installation Complete)
向导会自动创建数据库表、写入配置文件
config.php
。完成后,页面会提示“Your Moodle has been successfully installed!”。此时,
立刻执行一个关键动作
:
# 删除安装脚本,防止被恶意利用
sudo rm /var/www/moodle/install.php
这是 Moodle 安全最佳实践的第一步。
install.php
如果残留,攻击者可能通过它重装系统、覆盖现有数据。
4.2 首次登录后的必做五件事:从“能用”到“好用”
成功登录
http://moodle.school.edu
后,作为管理员,必须立即完成以下五项配置,否则 Moodle 只是一个空壳:
第一,配置
moodledata
目录路径。
进入
Site administration > Server > System paths
,在
Path to data directory
栏中输入
/var/moodledata
。这是 Moodle 找到其数据存储地的唯一途径,漏填则所有上传、缓存、日志功能失效。
第二,启用 HTTPS(SSL/TLS)。
即使只是内部网络,也必须启用 HTTPS。Ubuntu 16.04 的
certbot
(Let's Encrypt 客户端)对 Apache 支持完美。执行:
sudo apt install -y python-certbot-apache
sudo certbot --apache -d moodle.school.edu
Certbot 会自动修改 Apache 配置,添加 443 端口的 SSL 虚拟主机,并重定向 HTTP 到 HTTPS。Moodle 的
Site administration > Security > HTTP security
中,勾选
Use HTTPS for logins
和
Use HTTPS for entire site
。此举不仅加密传输,更能防止会话 Cookie 被窃取(
Secure
标志)。
第三,配置邮件服务。
Moodle 的通知(如课程邀请、作业提醒)依赖邮件。进入
Site administration > Plugins > Message outputs > Email
,启用 Email 插件。然后在
Site administration > Server > Email
中配置 SMTP:
-
SMTP hosts
:
smtp.gmail.com:587(若用 Gmail)或mail.your-school.edu:25(若用校内邮件服务器)。 -
SMTP username
:
your-admin@gmail.com -
SMTP password
:
App Password(Gmail 需生成应用专用密码,非账户密码)。 -
SMTP security
:
TLS
第四,安装并启用
local_cleanurls
插件,美化 URL。
默认的 Moodle URL 如
http://moodle.school.edu/course/view.php?id=2
极不友好。
local_cleanurls
插件可将其变为
http://moodle.school.edu/course/2
。下载地址:https://moodle.org/plugins/pluginversion.php?id=12345(以实际 ID 为准)。安装方法:
cd /var/www/moodle/local/
sudo wget https://github.com/your-repo/cleanurls/archive/master.zip
sudo unzip master.zip
sudo mv cleanurls-master cleanurls
sudo chown -R www-data:www-data cleanurls
然后在
Site administration > Plugins > Local plugins
中启用它。这一步大幅提升用户体验和 SEO。
第五,创建第一个课程并添加一名测试学生。
进入
Site administration > Courses > Add a new course
,填写课程名称、简称、描述。在
Course format
中,新手推荐
Topics
(主题格式),比
Weekly
(周格式)更直观。创建后,点击
Participants > Enrol users
,搜索并添加一个测试用户(如
student01
)。这是验证整个流程是否闭环的最终测试。
4.3 性能监控与日志分析:用原生工具做“医生”
Moodle 运行起来后,不能放任不管。Ubuntu 16.04 提供了强大的原生工具链,无需安装第三方 APM:
Apache 访问日志分析:
/var/log/apache2/moodle_access.log
记录了每一次 HTTP 请求。用
awk
快速统计 Top 10 最耗时的请求:
# 统计响应时间(第 7 列)最高的 10 个 URL
awk '{print $7, $11}' /var/log/apache2/moodle_access.log | sort -nr | head -10
若发现
/report/performance/index.php
或
/admin/tool/phpunit/cli/util.php
频繁出现,说明有人在后台执行耗时操作,需关注。
MySQL 慢查询日志:
在
/etc/mysql/mysql.conf.d/mysqld.cnf
中启用:
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
然后重启 MySQL。用
mysqldumpslow
分析:
sudo mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log
输出会显示执行时间最长的 10 个 SQL,如
SELECT * FROM mdl_course WHERE id = ?
,这提示你需要为
mdl_course.id
字段添加索引(它本就有,但若被误删则需重建)。
Moodle 自身日志:
Site administration > Reports > Logs
是最直观的界面。但更强大的是其数据库日志表
mdl_logstore_standard_log
。一个实用的 SQL 查询,找出最近一小时最活跃的用户:
SELECT userid, COUNT(*) as cnt
FROM mdl_logstore_standard_log
WHERE timecreated > UNIX_TIMESTAMP(NOW() - INTERVAL 1 HOUR)
GROUP BY userid
ORDER BY cnt DESC
LIMIT 10;
这能帮你快速定位是哪个老师在批量导入课程,或是哪个学生在刷课。
5. 常见问题与排查技巧实录:来自 17 个真实现场的故障快查表
5.1 白屏(Blank Page):最常见也最易解决的“幽灵故障”
现象:访问 Moodle 首页或任何页面,浏览器只显示一片空白,无错误信息,查看源码也是空的。
排查路径(按优先级排序):
-
检查 PHP 错误日志
:
sudo tail -f /var/log/apache2/error.log。最常见的原因是PHP Fatal error: Allowed memory size of 134217728 bytes exhausted,即memory_limit不足。解决方案:将/etc/php/7.0/apache2/php.ini中的memory_limit从128M提升到256M或512M,然后sudo systemctl restart apache2。 -
检查 Moodle
config.php权限 :sudo ls -l /var/www/moodle/config.php。如果权限不是-rw-r--r--(644),而是-rw-------(600),则 Apache 无法读取它,导致白屏。修复:sudo chmod 644 /var/www/moodle/config.php。 -
检查
moodledata目录所有权 :sudo ls -ld /var/moodledata。如果所有者不是www-data,则 Moodle 无法写入缓存,导致初始化失败。修复:sudo chown www-data:www-data /var/moodledata。
实操心得:我养成了一个习惯,在每次修改
php.ini或config.php后,都执行sudo -u www-data php /var/www/moodle/admin/cli/check_database.php。这个命令会以 Apache 用户身份运行 Moodle 的数据库检查脚本,能提前暴露权限和配置问题,比等用户报告白屏高效得多。
5.2 登录后无限重定向(Redirect Loop)
现象:输入用户名密码后,页面不断刷新,URL 在
/login/index.php
和
/my/
之间跳转,无法进入个人主页。
根本原因:HTTPS 配置不一致。
Moodle 的会话管理对协议极其敏感。如果 Apache 配置了 HTTPS 重定向,但 Moodle 的
config.php
中
$CFG->wwwroot
仍为
http://
开头,就会陷入重定向循环。
解决方案:
-
确认 Apache 的 HTTPS 虚拟主机已启用且工作正常(访问
https://moodle.school.edu应能打开)。 -
编辑
/var/www/moodle/config.php,找到$CFG->wwwroot行,将其改为https://moodle.school.edu。 - 清除浏览器缓存和 Cookie,重新登录。
5.3 上传大文件失败(Upload Max Filesize Exceeded)
现象:在课程中上传一个 50MB 的视频,选择文件后,页面弹出
File exceeds maximum file size
错误。
这不是单一配置问题,而是三层限制的叠加:
| 层级 | 配置项 | 位置 | 推荐值 |
|---|---|---|---|
| PHP 层 |
upload_max_filesize
|
/etc/php/7.0/apache2/php.ini
|
128M
|
| PHP 层 |
post_max_size
| 同上 |
128M
(必须 ≥
upload_max_filesize
)
|
| Apache 层 |
LimitRequestBody
|
/etc/apache2/sites-available/moodle.conf
|
134217728
(即 128MB)
|
操作步骤:
-
修改
php.ini中的两个值。 -
在 Apache 虚拟主机配置的
<Directory>块内,添加:LimitRequestBody 134217728 -
重启 Apache:
sudo systemctl restart apache2。
5.4 数据库连接失败(Can't connect to local MySQL server)
现象:安装向导卡在数据库测试步骤,或登录后首页报错
Error reading from database
。
排查清单:
-
✅
sudo systemctl status mysql:确认 MySQL 服务正在运行。 -
✅
sudo mysql -u moodle -p -D moodle:用 Moodle 数据库用户尝试登录,验证密码和权限。 -
✅
sudo netstat -tlnp | grep :3306:确认 MySQL 监听在127.0.0.1:3306,而非::1:3306(IPv6)。若只监听 IPv6,需在/etc/mysql/mysql.conf.d/mysqld.cnf中注释掉bind-address = ::1,并添加bind-address = 127.0.0.1。 -
✅
sudo cat /var/log/mysql/error.log:查看 MySQL 自身的错误日志,常有线索。
5.5 课程页面显示“Coding error detected”(编码错误)
现象:点击某个课程,页面报错
Coding error detected, it must be fixed by a programmer: Invalid get_string() identifier: 'pluginname'
。
这是典型的插件语言包缺失。
Moodle 的插件(如
mod_h5p
,
block_course_list
)都有自己的语言包。如果插件是手动下载 ZIP 安装的,其语言包可能未被自动部署。
解决方案:
- 进入 `Site administration > Language >

2037

被折叠的 条评论
为什么被折叠?



