我已经看过这两个:
- PHP:挂载 USB 设备
- 通过 php"exec"挂载时出错
但是,我的问题似乎有所不同。
我构建了一个广泛的库,用于调用Linux CLI工具。它是围绕proc_open
建造的,它是家庭和POSIX
。
正在使用它成功执行所有(直到我遇到这个mount
/umount
错误)CLI 工具。
现在,我正在构建一个 RAID 设置例程,它涉及 partprobe
、parted
- rm、mklabel、mkpart、mdadm
- 停止、零超级块、创建、dd
、mkfs
并最终mount
/umount
。
实际上有两个优雅的例程,一个用于组装 RAID,另一个用于拆卸。
正如标题所说,问题依赖于mount
和umount
。上面列出的其他工具及其命令已成功执行。
环境
Arch Linux - Linuxstone 3.11.6-1-ARCH #1 SMP PREEMPT 周五 10 月 18 日 23:22:36 CEST 2013 x86_64 GNU/Linux.
拱门正在运行systemd
- 可能是以某种方式影响了安装。
运行mod_php(最新)的 Apache Web 服务器(最新)。阿帕奇以http:http
运行。
http
在wheel
组中,wheels
是闺鸟 - %wheel ALL=(ALL) NOPASSWD: ALL
.
请不要在webserver
开始讨论完整的根功能 - 该单元是 NAS,它运行自定义 WebOS,并且仅用于内部网。即使有黑客攻击尝试 - 这些尝试很可能会破坏整个系统,这对客户来说是不健康的。NAS 是 Mobotix IP 摄像机的存储, 它运行大量依赖服务,并且这些单元已经部署在 30 多个对象中,没有问题.简而言之,webserver
不是为网络服务,而是为操作系统服务。
在写作之前,我添加了,为了快速测试,明确地http
sudoers - http ALL=(ALL) NOPASSWD: ALL
- 不起作用。
问题
在 RAID 组装过程中运行的最后一个命令是 mount /dev/md/stone':supershare /mnt/supershare
,它返回的退出代码为 0
。
执行后续装载会导致:
mount: /dev/md127 is already mounted or /mnt/supershare busy
/dev/md127 is already mounted on /mnt/supershare
退出代码为 32
。因此,阵列安装在某处。
在上述mount
之后执行umount /dev/md/stone':supershare
,返回退出代码 0
。执行后续umount
会导致:
umount: /dev/md/stone:supershare: not mounted
上面的命令是使用 sudo 自动运行的。
因此,它已成功安装并成功卸载,但是...我在 TTY0 上以root
身份登录,在执行mount
操作后运行lsblk
,但我没有看到mountpoint
:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 55.9G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part [SWAP]
├─sda3 8:3 0 12G 0 part /
└─sda4 8:4 0 16.6G 0 part /home
sdb 8:16 0 931.5G 0 disk
└─sdb1 8:17 0 899M 0 part
└─md127 9:127 0 1.8G 0 raid0
sdc 8:32 0 931.5G 0 disk
└─sdc1 8:33 0 899M 0 part
└─md127 9:127 0 1.8G 0 raid0
尝试从 TTY0 执行相同的mount
命令会成功挂载它(lsblk 在之后显示)。
如果我使用 CLI 工具mount
它,然后运行 mount -l
并使用 CLI 工具lsblk
,则挂载点是可见的。
立即以 root 身份从 TTY0 运行这两个命令,不显示挂载点。
重新启动,重置所有挂载(非自动挂载),然后,从 TTY0 挂载并从 TTY0 运行lsblk
将显示挂载点。
然后,使用 CLI 工具运行lsblk
,显示挂载点。
然后,使用 CLI 工具运行umount
,退出代码0
- 已卸载。
再次使用 CLI 工具运行lsblk
,不显示挂载点。
从 TTY0 运行lsblk
,仍会显示挂载点。
似乎当mount
/umount
使用我的 CLI 工具运行时,它会私下执行sudo
会话运行器的命令。
umount
在 TTY0 挂载后,确实会卸载它,但再次 - 私下。
从 TTY0 http
登录并在从 CLI 工具挂载 RAID 后运行lsblk
,则不会显示挂载点。这否定了"为sudo
会话运行器私下执行"。
我还在IBM的中找到了一个材料:
mount 命令使用实际用户 ID(而不是有效用户 ID)来确定用户是否具有适当的访问权。系统组成员可以发出设备装载,前提是他们对装载点和/etc/file systems 文件中指定的装载具有写入访问权限。具有 root 用户权限的用户可以发出任何挂载命令。
我希望我已经解释得足够好并且不会太混乱,我也希望你们能够帮助我在这里解决问题。
更新 (2013-10-28)
我尝试在 Web 上下文之外使用 CLI 工具进行测试,一个简单的 PHP 文件,我将与root
和自定义用户一起执行。
在这两种情况下,装载和卸载都成功。所以,它一定是Apache执行命令的东西,但是,我不明白为什么其他命令有效。
问题
是什么导致了这个问题,我该如何克服它?
简而言之,麻烦已经解决。
阿帕奇的相应systemd
服务,PrivateTmp=true
指令。显然,该指令使用新的文件系统命名空间执行进程。
这个问题在尝试调试和解决问题时,在互联网上催生了许多其他帖子。
- https://unix.stackexchange.com/questions/97897/sudo-mount-from-webserver-apache-by-mod-php-result-not-visible-by-root
- https://bbs.archlinux.org/viewtopic.php?id=172072
- https://unix.stackexchange.com/questions/98182/a-process-run-as-root-when-performing-mount-is-mounting-for-self-how-to-ma/98191#98191
每一个都源于我在这个过程中学到的东西。
我从获取有关mount
从事EUID
工作的更深入的信息开始。很快,我发现我的简单sudo
调用实际上没有用EUID 0
执行。这导致我对如何做到这一点提出了多个疑问,作为回报,催生了命令语法,如sudo -i 'su' -c 'mount /dev/sdb1 /mnt/firstone'
和其他衍生物。
由于解决方案没有成功,我看得更远。
我开始考虑尝试将条目添加到/etc/fstab
,这导致我遇到了大量权限问题。此外,sudo
和我的 CLI 工具被证明是不完整的。让我们带来大武器 - 让我们用-DBIG_SECURITY_HOLE
编译 Apache,也称为,让 Apache 可以按root
运行。
让我们将条目附加到tab
,让我们尝试挂载...和。。。失败!
经过无数次的测试、查询等等,我偶然发现了per process mount
,这些把我带到了这里,并向我打开了namespaces
的维度。
好的,这解释了一切 - 检查/proc/<pid>/mounts
验证它,现在,让我们更深入地啃咬,看看如何克服它。
同样,经过多次尝试但没有成功,我开始根据我对命名空间的新知识发布问题。缩小问题范围并变得更加技术化(至少我认为我做到了),这最终导致了一个用户 hiciu 向我指出systemd
方向,特别是 Apaches 服务 - PrivateTmp
。
瞧!。。。显然systemd
可以强制使用新的命名空间。
我有同样奇怪的 apache 行为,花了 3 天多的时间没有任何工作解决方案。然后幸运的是,我找到了这篇文章,正如您所描述的那样,PrivateTmp 导致了这个问题。就我而言,我尝试从 php 挂载驱动器:
<?php
...
exec("sudo mount /dev/sda1 /mnt/drive", $output, $ret);
...
?>
当我从 Web 浏览器运行上面的代码时,exec 函数返回 0(成功),我什至可以在代码中列出映射驱动器:
exec("ls /mnt/drive", $o, $r);
foreach ($o as $line){
echo $line.'<BR>';
}
但是当我尝试从cli搜索映射驱动器时,我看不到它。我尝试了所有内容,包括更改权限,更改php.ini等。直到现在,改变
PrivateTmp=false
在
/lib/systemd/system/apache2.service
能解决问题。非常感谢您的分享!
它正在搜索这个,看起来这种行为是通过 chroot 从 php 实现和检测的:
system('ischroot;echo $?');
设置PrivateTmp=true时给出0(说'你在chroot中'),在PrivateTemp=false时给出1。