PHP`require_once`包含错误的文件

PHP`require_once`包含错误的文件,php,linux,ext4,Php,Linux,Ext4,我在Linux Ubuntu 14.04-LTS机器上有这样一个开发树,有三个相同的分支: main -+-- leonardo --- project --- htdocs -+- panel --- index.php | | | +- config.php | +-- federico --- proje

我在Linux Ubuntu 14.04-LTS机器上有这样一个开发树,有三个相同的分支:

main -+-- leonardo --- project --- htdocs -+- panel --- index.php
      |                                    |
      |                                    +- config.php
      |
      +-- federico --- project --- htdocs -+- panel --- index.php
      |                                    |
      |                                    +- config.php
      |
      +-- carlo ------ project --- htdocs -+- panel --- index.php
      |                                    |
      |                                    +- config.php
    ..... (you get my drift).
没有软链接和硬链接。
config.php
文件位于svn ignore中,并且在所有分支之间都不同

有一个Apache服务器,每个开发人员都有一个virtualHost,所以我可以在或Federico的上看到我的开发版本

在调查当前的怪事时,两个文件是:

<?php // this is panel/index.php
    echo "I am " . __FILE__ . "\n";
    echo "I will include " . realpath('../config.php') . "\n";
    require_once '../config.php';

<?php // this is config.php
    echo "I am " . __FILE__ . "\n";
    exit();
但实际产出是:

I am leonardo/project/htdocs/panel/index.php
I will include /var/www/main/leonardo/project/htdocs/config.php
I am federico/project/htdocs/config.php
更奇怪的是

    echo "I will include " . realpath('../config.php') . "\n";
    require_once realpath('../config.php');
工作

TL;DR
要求_once
realpath
对“../config.php”的实际位置存在分歧

真正奇怪的是,我不知道运行在
leonardo/project/htdocs/panel/
中的脚本如何知道
federico/project/htdocs/config.php
;它应该向上搜索四个目录,然后搜索很多子目录

我几乎开始怀疑这可能与文件系统甚至内核有关

文件系统是
ext4
,内核是
3.13.0-55-generic\92 Ubuntu SMP Sun Jun 14 18:32:20 UTC 2015 x86\u 64 x86\u 64 GNU/Linux
。该计算机是最新VMware工作站上的虚拟x64

检查
  • PHP的
    include_path
    仅包括
    /usr/local/php5/pear
  • 如前所述,分支中没有任何文件是符号链接,所有相关文件的inode计数表明没有交叉链接。这些文件确实不同
  • 所有文件都在那里,这不是“最后一搏”
  • 从命令行中,在leonardo…面板中,我运行“cat../config.php”,并获得我的config.php,正如预期的那样。只有从PHP中才会包含错误的文件
  • 重启Apache(以防万一)毫无用处。接下来我将尝试重新启动整个虚拟机,但要做到这一点,我需要冻结几个服务,这将需要一段时间
  • 到昨天为止,一切都很顺利(那时我不在这里)。在过去的三天里,没有系统更新,没有重新启动,甚至没有远程登录。正常运行时间现在是八天
  • 我是个白痴:通过查看集成测试日志,我可以知道这是什么时候开始发生的。我已经问过了,午饭后等着他们

值得检查您的
include\u路径设置为什么(可以使用)

require
include
在给定绝对路径和相对路径的情况下表现不同。当你使用

require_once realpath('../config.php');
这就是:

require_once '/var/www/main/leonardo/project/htdocs/config.php';
正如你所期望的那样

以下几点很奇怪:

require_once '../config.php';

发生,因为PHP将检查包含路径中的每个条目是否有匹配的文件,并返回第一个匹配条目。因此,可能先检查federico配置的路径。

您是否检查了任何潜在的操作码缓存及其设置? 在过去,我在那里遇到了一些问题,例如没有检测到更改的文件

具体来说,如果设置为零,这种情况可能发生,并且将发生

opcache。使用\u cwd
boolean

如果启用,OPcache会将当前工作目录附加到脚本键,从而消除文件之间可能存在的冲突 相同的基本名称。禁用此指令可提高性能, 但可能会破坏现有应用程序

如果发生这种情况,第一个用户或phpunit脚本访问不同目录(例如
leonardo/config.php
vs
federico/config.php
)中给定名称的文件时,将使用该文件“初始化”缓存。文件系统功能(如
realpath
)将不受影响,并将继续工作。使用绝对路径的引用将继续工作具有相对路径的引用将以一种非常隐蔽的方式被破坏

因为,除非只有一个人在工作,否则这个人的缓存已经准备好满足他的需求,并且不会注意到任何东西。然后你回来工作,开始加载他的文件

另一方面,该设置可能会导致意外信息泄露,因为该设置是系统范围的。所以你知道你的ISP有一个坏的use\u cwd,你知道另一个站点包含“../inc/credit\u cards.php”,你在你的站点中准备了相同的路径并包含了一个同名文件
get\u defined\u vars()
可能会让您访问其他站点的登录或数据库系统。(尚未检查,但考虑到发生的情况,不知道为什么不检查)

更新 我检查了PHP5.6上的上述配置和一个旧的备份VM(我们有过去五年的时间机器快照:-))我确实能够读取我无权访问的不同虚拟主机中所有定义的全局变量,覆盖身份验证。 但是他们想到的测试并没有扩展到通过创建一个同名文件来诱使opcache包含其他人的文件

我也在我们当前的dev-VM上重新运行了相同的测试,问题似乎已经消失了,即使配置发生了很大的变化,我不确定它们是否具有可比性


我正在考虑将共享主机
config.inc.php
文件重命名为类似于
config.a72b1qTy.inc.php

的某种操作码缓存,这会造成干扰?系统确实使用了
opcache
。但我希望它已经被Apache重新启动清除了。。。?我不熟悉opcache操作;它是否在某处使用共享内存或临时文件?@Blizz,我发现opcache.ini文件是在集成测试开始出错之前被有缺陷的同步脚本修改的。在那之后,很容易发现血淋淋的细节。如果你发布一个这样的答案,我很乐意用这个故事来扩展它并接受。结果表明,当r
require_once '../config.php';