Я попытался создать файл трассировки с помощью fopen («имя», «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
Это кажется плохо документированной или объясненной особенностью PHP в системах, использующих systemd. Вместо того, чтобы создавать файл, в котором я указал PHP, вместо этого создаем файл еще одним слоем вниз частный каталог!
$ 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. Это является следствием решения 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");
На самом деле это Systemd функция безопасности: PrivateTmp
Вы можете отключить его для вашего конкретного HTTPD оказание услуг. На Arch Linux:
juergen@samson:/tmp → grep PrivateTmp /usr/lib/systemd/system/httpd.service
PrivateTmp=true
Других решений пока нет …