Я запускаю Bash-Scripts из PHP (5.4) с правами root через бинарную оболочку (см. [Выполнять команды root через PHP), которая прекрасно работает, за исключением следующего примера. Кроме того, я использую zfs-on-linux на CentOS7.
Я подготовил 2 простых примера Bash-Scripts:
test_zfsadd:
#!/bin/bash
#ARGS=1
err="$(zfs create $1 2>&1 > /dev/null)"
if [ $? -ne 0 ]
then
echo $err
exit 1
fi
echo "OK"exit 0
test_zfspart:
#!/bin/bash
#ARGS=1
msg="$(zfs get mounted $1 -H | awk '{print $3}')"
echo $msg
exit 0
Когда я вызываю соответствующие двоичные файлы из PHP с помощью e. г.
<?php
$partition = 'raid1/testpart';
$ret = shell_exec("/path/test_zfsadd_bin $partition");
echo "<p>Return value: $ret</p>\n";
$ret = shell_exec("/path/test_zfspart_bin $partition");
echo "<p>Is mounted: $ret</p>\n";
выход:
Return value: OK
Is mounted: yes
Это выглядит хорошо, но когда я вызываю ‘test_zfspart_bin raid1 / testpart’ прямо из консоли, я получаю правильный результат, который
no
(означает, что раздел НЕ смонтирован, проверено в / proc / mounts). Таким образом, я получаю 2 разных ответа из одного и того же сценария в зависимости от контекста. Сначала я подумал, что это как-то связано с битом SUID, но вызов скрипта в консоли с непривилегированным пользователем работает нормально. Если я попробую (как root)
zfs mount raid1/testpart
в консоли я получаю
filesystem 'raid1/testpart' is already mounted
cannot mount 'raid1/testpart': mountpoint or dataset is busy
что странно Я также не могу уничтожить «раздел» из консоли, это работает только из PHP. С другой стороны, если я создаю раздел как root непосредственно из bash и пытаюсь удалить его через PHP, он тоже не работает. Похоже, что разделы каким-то образом отделены друг от друга контекстом. Все синхронизируется снова, если я делаю
systemctl restart httpd
Я думаю, что Apache или PHP до некоторой степени поддерживают систему zfs, но я понятия не имею, почему и как. Любое объяснение или какой-то обходной путь высоко ценится.
Тем временем я сам понял это. Проблема была не в самом процессе apache, а в том, как он запускается systemd. Существует опция, называемая PrivateTmp, которая по умолчанию установлена в файле службы httpd (по крайней мере, в CentOS7). На странице руководства написано
PrivateTmp =
Принимает логический аргумент. Если true устанавливает новую файловую систему
пространство имен для выполняемых процессов и монтирует приватную / tmp
каталог внутри него, который не разделяется процессами вне
пространство имен. Это полезно для безопасного доступа к временным файлам
процесса, но делает совместное использование между процессами через / tmp
невозможно. По умолчанию false.
Это все объясняет, я думаю. Вновь созданный раздел zfs монтируется в этой «виртуальной» файловой системе и поэтому невидим для остальной системы, что в данном случае нежелательно. Процесс apache не может монтировать или размонтировать файловые системы вне своего пространства имен. После отключения опции все заработало как положено.
Других решений пока нет …