You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Moodle从IIS迁移至Nginx后FastCGI错误及图片404问题求助

Moodle迁移至Nginx后图片无法显示及FastCGI错误修复方案

问题现象

从Windows IIS迁移到Linux Nginx环境后,Nginx error.log频繁输出upstream prematurely closed FastCGI request while reading upstream错误,多数图片返回404无法正常显示。

错误日志片段:

2023/06/05 11:39:24 [error] 364769#364769: *4 upstream prematurely closed FastCGI request while reading upstream, client: 192.168.198.221, server: _, request: "GET /pluginfile.php?file=%2F1%2Ftheme_fordson%2Fslide1image%2F1685976991%2Funnamed%20%285%29.jpg HTTP/2.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "example.com", referrer: "https://example.com/theme/styles.php?theme=fordson&rev=1685976991_1&type=all"
2023/06/05 11:39:24 [error] 364769#364769: *4 upstream prematurely closed FastCGI request while reading upstream, client: 192.168.198.221, server: _, request: "GET /pluginfile.php?file=%2F1%2Ftheme_fordson%2Ffavicon%2F1685976991%2FUM-02.png HTTP/2.0", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "example.com", referrer: "https://example.com/my/"

当前配置文件

nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    proxy_read_timeout 300;
    proxy_connect_timeout 75;
    proxy_send_timeout 300;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;

        location /dataroot/ {
                internal;
                alias /moodle/data/moodledata/; # ensure the path ends with /
        }

    }

# Settings for a TLS enabled server.
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  _;
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/pki/nginx/wildcard.crt";
        ssl_certificate_key "/etc/pki/nginx/wildcard.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers PROFILE=SYSTEM;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;

        location /dataroot/ {
                internal;
                alias /moodle/data/moodledata/; # ensure the path ends with /
        }
    }

}

php.conf

index index.php index.html index.htm;

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_intercept_errors on;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_pass   php-fpm;
}

Moodle config.php

<?php  // Moodle configuration file

unset($CFG);
global $CFG;
$CFG = new stdClass();

$CFG->dbtype    = 'sqlsrv';
$CFG->dblibrary = 'native';
$CFG->dbhost    = '{HOST}';
$CFG->dbname    = '{DBNAME}';
$CFG->dbuser    = '{DBUSER}';
$CFG->dbpass    = '{DBPASS}';
$CFG->prefix    = 'mdl_';
$CFG->dboptions = array (
  'dbpersist' => 0,
  'dbport' => '',
  'dbsocket' => '',
);

$CFG->wwwroot   = 'https://example.com';
$CFG->dataroot  = '/moodle/data/moodledata/';
$CFG->admin     = 'admin';

$CFG->disableupdatenotifications = true;

$CFG->xsendfile = 'X-Accel-Redirect';
$CFG->xsendfilealiases = array(
        '/dataroot/' => $CFG->dataroot
);

$CFG->slasharguments = false;

$CFG->directorypermissions = 0777;

require_once(_DIR_ . '/lib/setup.php');

// There is no php closing tag in this file,
// it is intentional because it prevents trailing whitespace problems!

环境信息

  • PHP 7.4.33
  • Nginx 1.20.1

修复方案

1. 修复config.php语法错误

config.php中require_once(_DIR_ . '/lib/setup.php');存在语法错误,正确的魔术常量是双下划线的__DIR__,该错误会直接导致PHP脚本执行失败,触发FastCGI连接中断。

修改后代码:

require_once(__DIR__ . '/lib/setup.php');

2. 添加Nginx FastCGI超时配置

当前nginx.conf仅配置了proxy相关超时,缺少FastCGI超时设置,PHP处理静态文件转发请求时易因超时中断。在http块或对应server块中添加:

fastcgi_read_timeout 300;
fastcgi_connect_timeout 75;
fastcgi_send_timeout 300;

3. 验证moodledata目录权限

确保Nginx进程用户(默认是nginx)拥有/moodle/data/moodledata/目录的读取权限:

chown -R nginx:nginx /moodle/data/moodledata/
chmod -R 755 /moodle/data/moodledata/

同时确认Nginx中location /dataroot/的alias路径以/结尾,与$CFG->xsendfilealiases的映射完全匹配。

4. 调整slasharguments配置

当前$CFG->slasharguments = false;与Nginx中的rewrite ^/(.*\.php)(/)(.*)$ /$1?file=/$3 last;存在解析冲突。建议开启slasharguments:

$CFG->slasharguments = true;

并移除Nginx中的上述rewrite规则,Moodle原生支持slash参数格式,无需Nginx额外重写。

5. 检查php-fpm配置一致性

确认php-fpm的www.conf中listen配置与Nginx的fastcgi_pass一致:

listen = /run/php-fpm/www.sock

同时检查pm.max_children、pm.start_servers等进程参数是否足够,避免因进程资源不足导致请求中断。

6. 验证文件路径大小写一致性

Windows系统不区分路径大小写,Linux则严格区分。检查数据库中存储的文件路径与服务器实际路径是否完全匹配,尤其是主题相关图片(如theme_fordson下的文件)的路径大小写。

内容的提问来源于stack exchange,提问作者Abraham M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 15:44:52