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

时间:2019-03-06 02:01:08

标签: 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中获得任何有意义的信息。

这是测试代码:

test.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');
 ?>

问题:

问题1:您知道$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

其他说明:

  1. Ibu在我发布的代码的原始版本中指出了一个愚蠢的错字。哎呀!它在最后一分钟出现,是打字错误 WAS N'T 的问题。我仍然无法在/ tmp中“打开()”文件并从PHP 7.2对其进行写入。我曾经能够在PHP的早期版本(更早!)中做到这一点。

  2. 我只是仔细检查了一下:如果文件 AM 恰好位于本地目录中,我可以写该文件:

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

问:为什么????

更新

“它曾经起作用”的原因是systemd引入了Linux(较新版本),并附带了“ PrivateTmp”。

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

[Service]
...
PrivateTmp=true  <-- Changed this to "false"

其他注释为here

3 个答案:

答案 0 :(得分:3)

您的情况相反:if (!$fp)

您说的是如果不处理,则将其写入文件。应该相反。

<?php
  function PHPDBG ($s) {
    $fp = fopen ("/tmp/PHPDBG.txt", "a");
    if ($fp) { // fixed condition.
      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');
?>

答案 1 :(得分:2)

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

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

  2. 预期位置:/tmp/PHPDBG.txt

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

相关链接:

所以听起来这是某种系统化的“功能”(Grrr !!!!)。这就解释了为什么它“可以工作”(在Apache,PHP和Linux的早期版本中)。

解决方法

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

[Service]
...
PrivateTmp=true  <-- Changed this to "false"

答案 2 :(得分:-1)

真正的问题是权限问题。

创建私有 tmp 文件时,它只有 root 权限。

httpd 的权限应该是 httpd 等等。

这是一个 systemd 可配置项吗?似乎 systemd 解决了一个问题只是为了防止存在问题的实际使用。 httpd 的 /tmp 应该可以被 httpd 写入,但它不是。