【问题标题】:PHP is_writable false for NFS folder although files can be written尽管可以写入文件,但 NFS 文件夹的 PHP is_writable false
【发布时间】:2018-11-15 09:30:44
【问题描述】:

对不起,我不确定,如果这是正确的论坛,因为我不知道问题的原因,我正面临。

我在 Raspbian (Stretch 9) 上安装了 NextCloud,并将数据目录移动到已安装的 NFS 文件夹中。当我尝试访问 NextCloud 时,我收到错误消息“数据目录不可写”。

所以我挖得更深,最终可以将问题隔离到 PHP7.0 和 NFS 之间的交互:

由于某种原因,应用程序可以写入目录但 is_writable 返回 false。

我创建了以下 PHP 脚本:

<?php
$dirname = '/var/churros/data/nextcloud/';
//$dirname = '/tmp/';

$myfile = fopen($dirname.'newfile.txt', "w") or die("Unable to open file!");
$txt = "John Doe\n";
fwrite($myfile, $txt);
fclose($myfile);
echo nl2br("File ".$dirname."newfile.txt written\n");

if (touch($dirname.'/chkpt.tmp')) {
   echo nl2br("touch(".$dirname."/chkpt.tmp) successful\n");
} else {
   echo nl2br("touch(".$dirname."/chkpt.tmp) failed\n");
}

if (is_writable($dirname)) {
    echo 'Directory '.$dirname.' is writable';
} else {
    echo 'Directory '.$dirname.' is not writable';
}

phpinfo();
?>

结果是这样的

我的 NFS 被挂载为

192.168.1.100:/volume1/pidata/donut on /var/churros type nfs4 (rw,relatime,vers=4.0,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.103,local_lock=none,addr=192.168.1.100)

显然用户映射和访问权限是正确的:

namei -l /var/churros/web/nextcloud/
f: /var/churros/web/nextcloud/
drwxr-xr-x root     root     /
drwxr-xr-x root     root     var
drwxr-xr-x root     root     churros
drwxr-xr-x www-data www-data web
drwxrwxr-x www-data www-data nextcloud

在命令行上,作为用户 www-data,我也可以访问该目录并对其进行写入。

最后,SELinux 没有在盒子上安装/启用。

那么:知道为什么 PHP is_writable 在 NFS 目录上失败或者我如何调试这个 PHP 函数吗?

【问题讨论】:

  • 这里定义。 github.com/php/php-src/blob/… 虽然我看不出它失败的原因
  • is_dir 返回真还是假?
  • if [ -w "/var/churros/web/nextcloud" ]; then echo "WRITABLE"; else echo "NOT WRITABLE"; fi 作为 www 数据运行时显示什么
  • 也可以先试试 clearstatcache()
  • @FelippeDuarte - 谢谢:is_dir 返回 TRUE

标签: php raspbian nfs


【解决方案1】:

问题可能是 2 个不同系统的用户“www-data”的 unix 用户 ID 不同。

详细一点,从php src可以看出:

反过来:

是 virtual_access() 的便捷包装器

是围绕 access() 函数的线程安全包装器,它采用 考虑到每个线程的虚拟工作目录。

终于看到access() doc

access() 函数根据 amode 中包含的位模式检查由 path 参数指向的路径名命名的文件的可访问性,使用真实用户 ID 代替有效用户 ID 和真实组 ID有效组 ID 的位置。

access() linux documentation,它声明:

access() 在启用了 UID 映射的 NFS 文件系统上可能无法正常工作,因为 UID 映射是在服务器上完成的,并且对检查权限的客户端隐藏。 FUSE 安装座可能会出现类似问题。

试试:

var_dump(stat('nfs-filename'));

看看你得到了哪个uid

参考:

Similar issue with php session in nfs

【讨论】:

    【解决方案2】:

    这很可能是is_writable() 函数的错误。

    您可以修复这个 NextCloud 问题:

    } else if (!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) {
       //common hint for all file permissions error messages
       $permissionsHint = $l->t('Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.',
               [$urlGenerator->linkToDocs('admin-dir_permissions')]);
       $errors[] = [
               'error' => 'Your data directory is not writable',
               'hint' => $permissionsHint
       ];
    

    /usr/share/webapps/nextcloud/lib/private/Console/Application.php

    if ($input->getFirstArgument() !== 'check') {
           $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig());
           if (!empty($errors)) {
                   foreach ($errors as $error) {
                           $output->writeln((string)$error['error']);
                           $output->writeln((string)$error['hint']);
                           $output->writeln('');
                   }
                   throw new \Exception("Environment not properly prepared.");
           }
    }
    

    Source #1, Source #2

    【讨论】:

      猜你喜欢
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 2011-04-09
      • 2011-07-22
      • 1970-01-01
      相关资源
      最近更新 更多