【问题标题】:temp file created in different location than requested with systemd在不同于 systemd 请求的位置创建的临时文件
【发布时间】: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");

【问题讨论】:

    标签: php fopen systemd temp


    【解决方案1】:

    其实这是一个systemd安全功能:PrivateTmp

    您可以为您的特定 httpd 服务禁用它。在 Arch Linux 上:

    juergen@samson:/tmp → grep PrivateTmp /usr/lib/systemd/system/httpd.service 
    PrivateTmp=true
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-14
      • 2012-07-29
      • 2018-09-14
      • 2022-11-29
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多