I have some log files that I'm trying to delete through PHP and, despite what appear to be proper permissions, PHP's unlink command fails with a "Permission denied" error.
<?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());
?>
Output:
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 )
Containing folder permissions look okay (writable by apache):
$ ls -l /var/www/html/
drwxrwxr-x. 2 apache apache 407 Dec 29 22:55 foo
File permissions look okay:
$ ls -l /var/www/html/foo/
-rw-rw-r--. 1 apache apache 407 Dec 29 22:04 foo/bar.log
I stopped apache and ran in debug mode (apachectl -X
), found its PID, ran strace -p PID
, and opened test.php in my browser, and got this output:
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
Two things made it work:
- Running the PHP script directly as apache user:
su apache -c "php test.php"
- Deleting the folder and re-creating it. Works for a few hours and then starts failing with permission errors again.
Neither of those help me, since the PHP script needs to be run from httpd. Other things I've tried:
- Confirmed user is apache in http.conf
- Confirmed that httpd is running as apache by creating a file via PHP
- Restarted apache
- Looked for extended attributes (didn't see any)
- chmod 777 on the foo folder and log file (shouldn't be needed, but didn't help)
- Pulled my hair out (what's left)
Is there some reason that PHP's unlink would fail with a permissions error even when permissions are correct? Why would running test.php as apache directly work but fail with a permissions error for httpd when it's running as user apache as well?
The log files are created by a java process, but I don't think it's part of the issue – i.e., I killed the java process just in case it was doing something with the log files and PHP's unlink still fails.
Thanks for any tips on debugging PHP unlink permission denied errors.
I'm using CentOS 6.5, PHP 5.3.3.