为什么 PHP 7.2 fopen(/tmp, a) 不写入文件?

pau*_*sm4 6 php fopen systemd

我有一个旧的“PHPDBG”函数,可以让我“printf”到文本文件。

我“从永远”开始使用PHPDBG.inc(至少从 PHP 4.x 时代起),但它似乎无法在我当前的配置(ubuntu18、Apache 2.4.29 和 PHP 7.2)中工作。

具体来说:

  • 我无法打开该文件($fp 为空)...
  • /tmp/PHPDBG.txt 永远不会被创建(因为 fopen 失败)
  • /tmp 应该是世界可写的......并且......
  • 我似乎无法在 Apache error.log 中获取 PHP 错误,也无法从 或 中获取任何有意义的error_get_last()内容$php_errormsg

这是测试代码:

测试.php:

<?php
  function PHPDBG ($s) {
    $fp = fopen ("/tmp/PHPDBG.txt", "a");
    if ($fp) {
      // Successful open ... but nothing written!
      fputs($fp, $s . "\n");
      fclose($fp);
    } else {
      echo "<h3>FILE OPEN ERROR</h3>\n";
      echo "<p>" . print_r(error_get_last()) . "</p>\n";
      echo "<p>" . $php_errormsg . "</p>\n";
    }
  }

  PHPDBG('>>Hello');
  phpinfo();
  PHPDBG('<<Goodbye');
 ?>
Run Code Online (Sandbox Code Playgroud)

问题:

Q1:知道可能出了什么问题吗$fp = fopen ("/tmp/PHPDBG.txt", "a");

Q2:如果“fopen()”失败,我该怎么做才能得到有意义的错误消息?


附加信息:假设error_get_last()返回“1: EPERM 1 /* 不允许操作 */”,然后我手动创建 /tmp/PHPDBG.txt,chmod +rw,并再次尝试“test.php”。不行:我得到了完全相同的结果:$fp 为空,没有有意义的错误消息,并且 /tmp/PHPDBG.txt 没有更改:

root@ubuntu18:/tmp# umask 0
root@ubuntu18:/tmp# touch PHPDBG.txt
root@ubuntu18:/tmp# ls -l PHPDBG.txt
-rw-rw-rw- 1 root root 0 Mar  5 18:13 PHPDBG.txt
 <= Re-ran test here... failed exactly like before...
root@ubuntu18:/tmp# ls -l PHPDBG.txt
-rw-rw-rw- 1 root root 0 Mar  5 18:13 PHPDBG.txt
Run Code Online (Sandbox Code Playgroud)

补充笔记:

  1. Ibu 指出了我发布的代码的原始版本中的一个愚蠢的拼写错误。哎呀!它是在最后一刻悄悄出现的,打字错误不是问题所在。我仍然无法在 /tmp 中“fopen()”文件并从 PHP 7.2 写入该文件。我曾经能够在早期(非常早期!)版本的 PHP 中做到这一点。

  2. 我刚刚仔细检查过:如果该文件恰好位于本地目录中,我就能够写入该文件:

    // $fp = fopen ("/tmp/PHPDBG.txt", "a");  // Opens, but fails to write anything
    $fp = fopen ("PHPDBG.txt", "a");  // Works OK
    
    Run Code Online (Sandbox Code Playgroud)

问:为什么???

更新

“它曾经有效”的原因是 systemd 被引入(较新版本的)Linux,并带来了“PrivateTmp”。

我的解决方法是禁用Apache/PHP 的此“功能”。我编辑/etc/systemd/system/multi-user.target.wants/apache2.service如下:

[Service]
...
PrivateTmp=true  <-- Changed this to "false"
Run Code Online (Sandbox Code Playgroud)

附加说明请参见此处

pau*_*sm4 6

我发现似乎没有创建的文件:

  1. PHP代码:$fp = fopen ("/tmp/PHPDBG.txt", "a");

  2. 预计地点:/tmp/PHPDBG.txt.

  3. 实际位置:/tmp/systemd-private-c6f7629309e647818680f8a6ee1105d6-apache2.service-lGKGc6/tmp/PHPDBG.txt

相关链接:

所以听起来这是某种 systemd“功能”(咕噜!!!)。这解释了为什么它“曾经有效”(在 Apache、PHP 和 Linux 的早期版本中)。

解决方法

我编辑/etc/systemd/system/multi-user.target.wants/apache2.service

[Service]
...
PrivateTmp=true  <-- Changed this to "false"
Run Code Online (Sandbox Code Playgroud)

  • 我分享你的感受。希望我的帖子能为您节省一些时间和麻烦:) (2认同)