我有一些我试图通过PHP删除的日志文件,尽管看起来是正确的权限,但PHP的unlink命令失败并且"权限被拒绝"错误。
<?php
$path = 'foo/bar.log';
echo 'user = ' . get_current_user() . '<br/>';
echo 'owner = ' . fileowner($path) . '<br/>';
echo 'fileperms = ' . substr(sprintf('%o',fileperms($path)), -4) . '<br/>';
@unlink($path);
print_r(error_get_last());
?>
输出:
user = apache
owner = 48 ← apache
fileperms = 0664
Array ( [type] => 2 [message] => > unlink(foo/bar.log): Permission denied
[file] => /var/www/html/test.php [line] => 6 )
包含文件夹权限看起来没问题(writable by apache):
$ ls -l /var/www/html/
drwxrwxr-x. 2 apache apache 407 Dec 29 22:55 foo
文件权限看起来没问题:
$ ls -l /var/www/html/foo/
-rw-rw-r--. 1 apache apache 407 Dec 29 22:04 foo/bar.log
我停止了apache并以调试模式(apachectl -X
)运行,找到了它的PID,运行了strace -p PID
,并在我的浏览器中打开了test.php,得到了这个输出:
setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={30, 0}}, NULL) = 0
lstat("/var/www/html/test.php", {st_mode=S_IFREG|0644, st_size=74, ...}) = 0
open("/var/www/html/test.php", O_RDONLY) = 16
fstat(16, {st_mode=S_IFREG|0644, st_size=74, ...}) = 0
fstat(16, {st_mode=S_IFREG|0644, st_size=74, ...}) = 0
fstat(16, {st_mode=S_IFREG|0644, st_size=74, ...}) = 0
mmap(NULL, 74, PROT_READ, MAP_SHARED, 16, 0) = 0x7fad849f6000
munmap(0x7fad849f6000, 74) = 0
close(16) = 0
unlink("foo/bar.log") = -1 EACCES (Permission denied)
write(9, "[Sun Dec 29 12:40:39 2013] [erro"..., 188) = 188
chdir("/var/www/html") = 0
有两件事使它成功:
su apache -c "php test.php"
这些都没有帮助我,因为PHP脚本需要从httpd运行。我尝试过的其他事情:
即使权限正确,是否有某些原因导致PHP的取消链接失败且权限错误?为什么运行test.php作为apache直接工作但是当httpd作为用户apache运行时失败并出现权限错误?
日志文件是由java进程创建的,但我不认为它是问题的一部分 - 也就是说,我杀了java进程,以防万一它对日志文件和PHP的unlink仍然失败。
感谢有关调试PHP unlink权限被拒绝错误的任何提示。
我使用的是CentOS 6.5,PHP 5.3.3。