【发布时间】:2016-07-16 20:01:49
【问题描述】:
我尝试使用 fopen("name","a") 创建一个跟踪文件并写入它,但是尽管 fopen 成功并返回了一个句柄,并且所有 fwrite 调用都成功了,但我在以下位置找不到该文件fopen 的文件名参数指定的位置。
$trace = fopen("/var/tmp/billing.log", "a");
if ($trace)
echo "opened /var/tmp/billing.log<br>\n";
else
echo "unable to open /var/tmp/billing.log<br>\n";
...
fwrite($trace, __FILE__ . ': ' . __LINE__ . "ce(" .
"\$aid=$aid, " .
"\$level=$level, " .
"\$id=$id, " .
"\$mode=$mode, " .
"\$nocache=$nocache)\n");
echo __FILE__ . ': ' . __LINE__ . "ce(" .
"\$aid=$aid, " .
"\$level=$level, " .
"\$id=$id, " .
"\$mode=$mode, " .
"\$nocache=$nocache)<br>\n";
显示表示句柄已返回的回显,每次调用 fwrite 后立即显示回显,但请求的文件 /var/tmp/billing.log 不存在。像往常一样 /var/tmp 是:
drwxrwxrwt. 35 root root 4096 Jul 15 20:06 tmp
所以允许写入目录。我通过以下方式手动创建文件对此进行了测试:
cat > /var/tmp/test
这似乎是使用 systemd 的系统上 PHP 的一个记录或解释不充分的特性。不是在我指定 PHP 的地方创建文件,而是在 private 目录中创建文件的更下一层!
$ cd /var/tmp
$ sudo find -name *.log
[sudo] password for jcobban:
./systemd-private-DGOkBT/tmp/recur-billing.log
./systemd-private-DGOkBT/tmp/process-registration.log
./systemd-private-uEF6lO/tmp/recur-billing.log
./systemd-private-uEF6lO/tmp/billing.log
./systemd-private-uEF6lO/tmp/process-registration.log
$ ls systemd-private-uEF6lO/
ls: cannot open directory systemd-private-uEF6lO/: Permission denied
请注意,我必须使用 sudo 才能查看文件,因为我没有使用 PHP 进程的用户 ID 运行。这是 PHP 决定使用 systemd 的私有临时目录服务的结果。 PHP 文档中的任何地方似乎都没有描述此操作。如果您调用函数 sys_get_temp_dir 它甚至会谎报临时文件的位置。请注意,使用私有临时目录的决定不会影响 PHP 脚本本身,因为临时文件名总是被映射的。从脚本的角度来看,文件位于程序指定的位置。即 fopen("/var/tmp/billing.log", "r");将读取文件。问题仅在于临时文件的外部可见性。我还没有检查,但我怀疑在 Windows 上 PHP 将 /tmp 和 /var/tmp 映射到 Windows 临时目录 C:\Windows\Temp\ 以实现可移植性。
这很痛苦,因为为了使这些跟踪文件对外部分析可见,我现在必须定义和管理我自己的目录来放置跟踪文件,这是一个复杂的操作,因为在我的站点上“DOCUMENT_ROOT”不是有效路径,所以我必须弄清楚文档根目录的真实路径是什么。
$document_root = substr(__FILE__, 0, -strlen($_SERVER['PHP_SELF']));
$trace = fopen($document_root . "/log/billing.log", "a");
【问题讨论】: