Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't PHP 7.2 fopen(/tmp, a) write to the file?

Tags:

php

fopen

systemd

I have an old "PHPDBG" function that lets me "printf" to a text file.

I've had PHPDBG.inc "since forever" (at least since PHP 4.x days), but it doesn't seem to be working in my current configuration (ubuntu18, Apache 2.4.29 and PHP 7.2).

Specifically:

  • I can't open the file ($fp is null) ...
  • /tmp/PHPDBG.txt never gets created (because of the fopen failure)
  • /tmp should be world-writable ... and ...
  • I don't seem to be able to get a PHP error in the Apache error.log, or get anything meaningful from either error_get_last() or $php_errormsg.

Here is the test code:

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

Questions:

Q1: Any idea what might be wrong with $fp = fopen ("/tmp/PHPDBG.txt", "a");?

Q2: What can I do to get a meaningful error message if "fopen()" fails?


Additional info: assuming error_get_last() is returning "1: EPERM 1 /* Operation not permitted */", then I manually created /tmp/PHPDBG.txt, chmod +rw, and tried "test.php" again. No-go: I got exactly the same results: $fp was null, no meaningful error messages, and /tmp/PHPDBG.txt was unchanged:

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

Additional notes:

  1. Ibu pointed out a stupid typo in the original version of the code I posted. Whoops! It crept in at the last minute, the typo WASN'T the problem. I'm still not able to "fopen()" a file in /tmp and write to it from PHP 7.2. I used to be able to do this in earlier (MUCH earlier!) versions of PHP.

  2. I just double-checked: I AM able to write to the file if it happens to be in the local directory:

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

Q: Why????

Update

The reason "it used to work" is that systemd was introduced to (newer versions of) Linux, bringing with it "PrivateTmp".

My workaround was to disable this "feature" for Apache/PHP. I edited /etc/systemd/system/multi-user.target.wants/apache2.service as follows:

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

Additional notes are here.

like image 336
paulsm4 Avatar asked Mar 06 '19 02:03

paulsm4


2 Answers

I found the file that didn't seem to be created:

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

  2. Expected location: /tmp/PHPDBG.txt.

  3. Actual location: /tmp/systemd-private-c6f7629309e647818680f8a6ee1105d6-apache2.service-lGKGc6/tmp/PHPDBG.txt

Relevant links:

  • Php has its own /tmp in /tmp/systemd-private-nABCDE/tmp when accessed through nginx

  • Why PHP cannot see /tmp

So it sounds like this is some kind of systemd "feature" (Grrr!!!!). Which explains why it "used to work" (in previous versions of Apache, PHP and Linux).

Workaround

I edited /etc/systemd/system/multi-user.target.wants/apache2.service:

[Service]
...
PrivateTmp=true  <-- Changed this to "false"
like image 65
paulsm4 Avatar answered Sep 28 '22 00:09

paulsm4


Your condition is reversed: if (!$fp).

You are saying if not handle, then write to the file. It should be the opposite.

<?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');
?>
like image 32
Ibu Avatar answered Sep 28 '22 02:09

Ibu