为什么 PHP 7.2 fopen(/tmp, a) 不写入文件?
Why doesn't PHP 7.2 fopen(/tmp, a) write to the file?
我有一个旧的 "PHPDBG" 函数可以让我 "printf" 到一个文本文件。
我有 PHPDBG.inc "since forever"(至少从 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');
?>
问题:
Q1:知道 $fp = fopen ("/tmp/PHPDBG.txt", "a");
有什么问题吗?
问题 2:如果 "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
补充说明:
Ibu 指出了我发布的代码的原始版本中的一个愚蠢的拼写错误。哎呀!它是在最后一刻悄悄出现的,错字 不是 的问题。我仍然无法 "fopen()" /tmp 中的文件并从 PHP 7.2 写入它。我曾经能够在 PHP.
的早期(更早!)版本中做到这一点
我刚刚仔细检查:我 AM 能够写入文件,如果它恰好在本地目录中:
// $fp = fopen ("/tmp/PHPDBG.txt", "a"); // Opens, but fails to write anything
$fp = fopen ("PHPDBG.txt", "a"); // Works OK
问:为什么????
更新
"it used to work" 的原因是 systemd 被引入到 Linux 的(较新版本),带来了 "PrivateTmp".
我的解决方法是为Apache/PHP禁用这个"feature"。我编辑 /etc/systemd/system/multi-user.target.wants/apache2.service
如下:
[Service]
...
PrivateTmp=true <-- Changed this to "false"
附加说明是 。
你的条件反转了: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');
?>
我发现好像没有创建的文件:
PHP代码:$fp = fopen ("/tmp/PHPDBG.txt", "a");
预期位置:/tmp/PHPDBG.txt
.
实际位置:/tmp/systemd-private-c6f7629309e647818680f8a6ee1105d6-apache2.service-lGKGc6/tmp/PHPDBG.txt
相关链接:
所以这听起来像是某种 systemd "feature"(Grrr!!!!)。这解释了为什么它 "used to work"(在以前的 Apache 版本中,PHP 和 Linux)。
解决方法
我编辑了 /etc/systemd/system/multi-user.target.wants/apache2.service
:
[Service]
...
PrivateTmp=true <-- Changed this to "false"
真正的问题是权限问题。
创建私有 tmp 文件时,它仅具有 root 权限。
httpd的权限应该是httpd等等。
这是systemd可配置项吗?似乎 systemd 解决了一个问题只是为了防止存在问题的实际使用。 httpd 的 /tmp 应该可以由 httpd 写入,但事实并非如此。
我有一个旧的 "PHPDBG" 函数可以让我 "printf" 到一个文本文件。
我有 PHPDBG.inc "since forever"(至少从 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');
?>
问题:
Q1:知道 $fp = fopen ("/tmp/PHPDBG.txt", "a");
有什么问题吗?
问题 2:如果 "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
补充说明:
Ibu 指出了我发布的代码的原始版本中的一个愚蠢的拼写错误。哎呀!它是在最后一刻悄悄出现的,错字 不是 的问题。我仍然无法 "fopen()" /tmp 中的文件并从 PHP 7.2 写入它。我曾经能够在 PHP.
的早期(更早!)版本中做到这一点
我刚刚仔细检查:我 AM 能够写入文件,如果它恰好在本地目录中:
// $fp = fopen ("/tmp/PHPDBG.txt", "a"); // Opens, but fails to write anything $fp = fopen ("PHPDBG.txt", "a"); // Works OK
问:为什么????
更新
"it used to work" 的原因是 systemd 被引入到 Linux 的(较新版本),带来了 "PrivateTmp".
我的解决方法是为Apache/PHP禁用这个"feature"。我编辑 /etc/systemd/system/multi-user.target.wants/apache2.service
如下:
[Service]
...
PrivateTmp=true <-- Changed this to "false"
附加说明是
你的条件反转了: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');
?>
我发现好像没有创建的文件:
PHP代码:
$fp = fopen ("/tmp/PHPDBG.txt", "a");
预期位置:
/tmp/PHPDBG.txt
.实际位置:
/tmp/systemd-private-c6f7629309e647818680f8a6ee1105d6-apache2.service-lGKGc6/tmp/PHPDBG.txt
相关链接:
所以这听起来像是某种 systemd "feature"(Grrr!!!!)。这解释了为什么它 "used to work"(在以前的 Apache 版本中,PHP 和 Linux)。
解决方法
我编辑了 /etc/systemd/system/multi-user.target.wants/apache2.service
:
[Service]
...
PrivateTmp=true <-- Changed this to "false"
真正的问题是权限问题。
创建私有 tmp 文件时,它仅具有 root 权限。
httpd的权限应该是httpd等等。
这是systemd可配置项吗?似乎 systemd 解决了一个问题只是为了防止存在问题的实际使用。 httpd 的 /tmp 应该可以由 httpd 写入,但事实并非如此。