即使具有广泛的权限,PHP fopen()也会在文件上失败

时间:2011-09-08 23:49:55

标签: php apache permissions

我正在将我的LAMP从我的Windows服务器迁移到运行Debian 6的VPS。大多数工作都正常,但是,其中一个PHP脚本无法写入其配置的日志文件。我无法确定原因,所以我写了一个新的,简单的,有人工作的PHP脚本来测试这个问题。

<?php
        ini_set('display_errors', 1);
        error_reporting(E_ALL);
        echo exec('whoami');
        $log = fopen('/var/log/apache2/writetest/writetest.log', 'a');
        if ($log != NULL)
        {
                fflush($log);
                fclose($log);
                $log = NULL;
        }
?>

然而,结果失败了:

www-data Warning: fopen(/var/log/apache2/writetest/writetest.log): failed to open stream: Permission denied in /var/www/_admin/phpwritetest.php on line 5 
  • 虽然我永远不会这样做,但为了帮助诊断,我将/var/log/apache2/writetest/writetest.log设置为chmod 777.
  • 目录和文件都归www-data:www-data所有。
  • 该文件是使用touch创建的。

我运行了strace来验证哪个进程正在执行open:

[pid 21931] lstat("/var/log/apache2/writetest/writetest.log", 0x7fff81677d30) = -1 EACCES (Permission denied)
[pid 21931] lstat("/var/log/apache2/writetest", 0x7fff81677b90) = -1 EACCES (Permission denied)
[pid 21931] open("/var/log/apache2/writetest/writetest.log", O_RDWR|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)

我检查过,pid 21931确实是在www-data下运行的apache2子进程之一。如您所见,我还在脚本中包含echo exec('whoami');,该脚本确认脚本由www-data运行。

其他说明:

  • PHP未以安全模式运行
  • 未设置PHP open_basedir
  • 版本信息:Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze3 with Suhosin-Patch mod_ssl/2.2.16 OpenSSL/0.9.8o
  • uname -a:2.6.32-238.19.1.el5.028stab092.2 #1 SMP Thu Jul 21 19:23:22 MSD 2011 x86_64 GNU/Linux
  • 这是在OpenVZ下运行的VPS
  • ls -l(file):-rwxrwxrwx 1 www-data www-data 0 Sep 8 18:13 writetest.log
  • ls -l(目录):drwxr-xr-x 2 www-data www-data 4096 Sep 8 18:13 writetest
  • Apache2的父进程在root下运行,子进程在www-data
  • 下运行
  • 未安装selinux(感谢Fabio提醒我提及此事)
  • 我已多次重启apache并重新启动服务器

3 个答案:

答案 0 :(得分:13)

请记住,为了访问文件,所有父目录必须可由www-data读取。 strace输出似乎表明即使访问 /var/log/apache2/writetest也失败了。确保www-data具有以下目录的权限:

  • / (r-x)
  • /var (r-x)
  • /var/log (r-x)
  • /var/log/apache2 (r-x)
  • /var/log/apache2/writetest (rwx)
  • /var/log/apache2/writetest/writetest.log (rw-)

答案 1 :(得分:0)

写文件的php文件是否设置了适当的权限?尝试更改这些以查看是否存在问题。

答案 2 :(得分:0)

可能是SELinux问题,即使Debian没有在您的提供商可能启用它的默认安装中发送它。使用

/var/log中查找邮件
grep -i selinux /var/log/{syslog,messages}

如果这是原因而你需要禁用它,这里有说明:查找文件/etc/selinux/config,这是默认内容。将SELINUX指令更改为disabled并重新启动系统。

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#   enforcing - SELinux security policy is enforced.
#   permissive - SELinux prints warnings instead of enforcing.
#   disabled - SELinux is fully disabled.
SELINUX=disabled
# SELINUXTYPE= type of policy in use. Possible values are:
#   targeted - Only targeted network daemons are protected.
#   strict - Full SELinux protection.
SELINUXTYPE=targeted