我在这样的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,所以我可以在http://leonardo.project.local或Federico的http://federico.project.local看到我的开发版本。
在调查当前的怪异时,这两个文件是:
<?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 leonardo/project/htdocs/config.php
但实际输出是:
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 require_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_64 x86_64 x86_64 GNU/Linux
。该机器是最新VMware Workstation上的虚拟x64。
include_path
仅包含.
和/usr/local/php5/pear
。答案 0 :(得分:3)
值得检查include_path
设置的内容(可以使用get_include_path完成此操作)。
require
和include
的行为会有所不同。当你使用
require_once realpath('../config.php');
这样做:
require_once '/var/www/main/leonardo/project/htdocs/config.php';
哪种方式可以预期。
以下的奇怪之处:</ p>
require_once '../config.php';
发生是因为PHP将检查匹配文件的include路径中的每个条目并返回第一个匹配的条目。因此,可能首先检查federico配置的路径。
答案 1 :(得分:1)
您是否检查过任何潜在的操作码缓存及其设置? 在过去,我遇到了一些问题,例如没有检测到已更改的文件。
具体而言,如果opcache.use_cwd
设置为零,则可能会出现 。
opcache.use_cwd
布尔如果启用,OPcache会将当前工作目录附加到脚本键,从而消除文件之间可能发生的冲突 相同的基本名称。禁用此指令可提高性能, 但可能会破坏现有应用。
如果发生这种情况,那么第一个用户或phpunit脚本访问另一个目录中的给定名称的文件(例如leonardo/config.php
vs {{1将使用该文件“填充”缓存。 federico/config.php
等文件系统功能不会受到影响,并将继续工作。使用绝对路径的引用将继续工作。 相对路径的引用将以一种非常阴险的方式被破坏。
在你只有一个人工作之前,那个人已经根据他的需要准备了缓存,并且什么也没注意到。然后你重新开始工作,然后开始加载他的文件。
在旁注中,该设置可能会导致无意的信息泄露,因为该设置是系统范围。所以你知道你的ISP有一个破坏的use_cwd,你知道另一个站点包含'../inc/credit_cards.php',你在你的站点中准备相同的路径并包含一个相同的文件名称。 realpath
可能会让您使用其他站点的登录或数据库系统。 (没有检查过,但考虑到发生了什么,不明白为什么不这样做。)