-1

我通过二进制包装器以 root 权限从 PHP (5.4) 运行 Bash-Scripts(请参阅 [通过 PHP 执行 root 命令),除了以下示例外,它工作得非常好。另外,我在 CentOS7 上使用 zfs-on-linux。

我准备了 2 个简单的示例 Bash 脚本:

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 调用相应的二进制文件时,例如

<?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-Bit 有关,但是在控制台中使用非特权用户调用脚本可以正常工作。如果我尝试(以 root 身份)

zfs mount raid1/testpart

在控制台中我得到

filesystem 'raid1/testpart' is already mounted
cannot mount 'raid1/testpart': mountpoint or dataset is busy

这很奇怪。我也无法从控制台销毁“分区”,这仅适用于 PHP。另一方面,如果我直接从 bash 以 root 身份创建一个分区并尝试通过 PHP 删除它,它也不起作用。看起来分区以某种方式通过上下文彼此分离。如果我这样做,一切都会再次同步

systemctl restart httpd

我认为 apache 或 PHP 在某种程度上使 zfs 系统保持忙碌,但我完全不知道为什么以及如何。非常感谢任何解释或一些解决方法。

4

1 回答 1

0

与此同时,我自己也想通了。问题不在于 apache 进程本身,而在于 systemd 是如何启动它的。有一个选项叫做'PrivateTmp',默认情况下在httpd服务文件中设置为'true'(至少在CentOS7中)。手册页说

PrivateTmp= 采用布尔参数。如果 true 为已执行的进程设置一个新的文件系统命名空间,并在其中挂载一个私有 /tmp 目录,则该目录不被命名空间之外的进程共享。这对于保护对进程临时文件的访问很有用,但无法通过 /tmp 在进程之间进行共享。默认为假。

这解释了我所想的一切。新创建的 zfs 分区安装在这个“虚拟”文件系统中,因此对系统的其余部分不可见,这在这种情况下是不希望的。apache 进程无法在其命名空间之外挂载或卸载文件系统。禁用该选项后,一切都按预期工作。

于 2015-11-19T01:25:53.620 回答