PHP is_writable false для папки NFS, хотя файлы могут быть записаны - PullRequest
0 голосов
/ 05 июня 2018

Извините, я не уверен, что это правильный форум, потому что я не знаю причину проблемы, с которой сталкиваюсь.

Я установил NextCloud на Raspbian (Stretch 9)и переместил каталог данных в смонтированную папку 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-daТо есть, я могу получить доступ к каталогу и написать в него.

Наконец, SELinux не установлен / включен на коробке.

Итак: Любая идея, почему PHPОшибка is_writable в каталоге NFS или как я могу отладить эту функцию PHP?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Проблема может заключаться в том, что идентификатор пользователя unix отличается для пользователя "www-data" для 2 разных систем.

Подробно, от php src , вы можете видеть, что:

В свою очередь:

- это удобная оболочка для virtual_access ()

- это потокобезопасная оболочка для функции access (), которая учитывает виртуальные рабочие каталоги для каждого потока.

Наконец, ищем access () doc :

Функция access () проверяет файл с именем pathname, на который указывает аргумент path, на доступность в соответствии с битовой комбинациейпротивс использованием действительного идентификатора пользователя вместо действующего идентификатора пользователя и реального идентификатора группы вместо действующего идентификатора группы.

, а также в документации access () linux говорится:

access () может работать некорректно в файловых системах NFS с UIDсопоставление включено, поскольку сопоставление UID выполняется на сервере и скрыто от клиента, который проверяет разрешения.Подобные проблемы могут возникнуть с креплениями FUSE.

Попробуйте:

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

и посмотрите, какой идентификатор вы получите.

Ссылка:

Подобная проблема с php-сессией в nfs

0 голосов
/ 11 июня 2018

Скорее всего, это ошибка 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
   ];

AND

/ 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.");
       }
}

Источник № 1 , Источник № 2

...