preload.php路径必须为绝对路径且php-fpm worker用户有读权限,否则静默失败或报“failed to open stream”;需设opcache.preload_user指定预加载用户,修改后必须完整重启php-fpm。

preload.php路径必须绝对且PHP进程有读权限
最常见的报错是 Failed to open stream: No such file or directory,本质是PHP-FPM worker进程找不到或打不开你指定的 preload.php。它不是用当前工作目录解析的,而是以PHP-FPM主进程启动时的用户身份(通常是 www-data 或 nginx)去读取文件,所以相对路径、软链接未解、父目录无执行权限(x)都会失败。
- 必须用绝对路径,比如
opcache.preload=/var/www/app/preload.php,别写成./preload.php或../config/preload.php - 确认该文件所有者和组对PHP运行用户可读:
sudo chown www-data:www-data /var/www/app/preload.php;父目录至少要有rx权限 - 如果 preload.php 里用了
require_once加载其他文件,那些路径也得是绝对路径,或确保include_path已设好
preload.php里不能调用动态函数或依赖未加载扩展
预加载发生在PHP-FPM master进程启动、worker fork之前,此时很多运行时环境还没就绪——比如 $_SERVER 为空、ini_set() 无效、PDO/Redis等扩展虽已加载但连接尚未建立。任何试图在 preload.php 中执行数据库查询、发HTTP请求、或调用未启用扩展的函数,都会直接导致PHP-FPM启动失败,日志里只显示 segmentation fault 或 failed to preload。
- 只允许静态加载:用
require、require_once、opcache_compile_file();禁止file_get_contents()、curl_init()、new PDO()等 - 检查扩展是否已启用:
php -m | grep pdo,若没输出,preload里用PDO类就会报Class 'PDO' not found - 避免在preload.php中定义函数或类以外的逻辑,比如
echo "loading...";会触发输出,导致FPM启动中断
opcache.preload_user必须显式设置,否则root下启动直接拒绝
Ubuntu 24.04 + PHP 8.3 默认以 root 启动PHP-FPM master,但OPcache默认禁止root预加载,不设 opcache.preload_user 就会静默跳过,或者报 Preloading disabled: opcache.preload_user is not set。这不是警告,是硬性拦截。
- 要么设为实际运行worker的用户:
opcache.preload_user=www-data - 要么明确允许root:
opcache.preload_user=root(仅限开发或容器内可控环境) - 这个配置必须写在全局
php.ini或/etc/php/8.3/fpm/conf.d/10-opcache.ini里,不能放在.htaccess或ini_set()中
预加载后修改代码不生效?这是设计行为,不是bug
很多人配完发现改了类文件,重启Nginx也没用,一查 opcache_get_status()['preloaded_scripts'] 还在,以为配错了。其实这是预加载的核心机制:所有被 preload.php 加载的脚本,在整个PHP-FPM生命周期内都锁定在共享内存中,磁盘文件变更完全不触发重载。
- 这是预期行为,不是故障。适合加载框架核心、基础工具类、路由表等几乎不变的代码
- 上线新版本必须重启PHP-FPM:
sudo systemctl restart php8.3-fpm,而不是只 reload - 开发调试阶段建议先关掉预加载(注释掉
opcache.preload),或把validate_timestamps=1和revalidate_freq=1配合使用,但生产环境别这么干
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











