我们正在将产品从 Centos 6 更新到 Centos 8,并且在通过 apache 挂载卷时发现了奇怪的行为。
网页通过 apache/php 提供 UI 前端来挂载/卸载分区。但是,通过 apache/php 安装的设备不会在 shell 中显示为“已安装”。
例如,通过这个小程序安装包含 Centos 安装程序的 USB 记忆棒会显示设备已安装、已卸载,并且可以列出内容:
<?php
function runCmd($cmd)
{
print "$cmd<br />\n";
exec($cmd, $lines);
foreach($lines as $l)
{
print "$l<br />\n";
}
print "<br />\n";
}
runCmd("mount | grep /dev/sd");
runCmd("/usr/bin/sudo -n umount /mnt/usb");
runCmd("mount | grep /dev/sd");
runCmd("/usr/bin/sudo -n /usr/bin/mount /dev/sdb1 /mnt/usb 2>&1");
runCmd("mount | grep /dev/sd");
runCmd("grep sd /etc/mtab");
runCmd("grep sd /proc/mounts");
runCmd("ls /mnt/usb");
?>
网页输出:
mount | grep /dev/sd
/dev/sda1 on /boot type ext4 (rw,relatime)
/dev/sdb1 on /mnt/usb type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
/usr/bin/sudo -n umount /mnt/usb
mount | grep /dev/sd
/dev/sda1 on /boot type ext4 (rw,relatime)
/usr/bin/sudo -n /usr/bin/mount /dev/sdb1 /mnt/usb 2>&1
mount | grep /dev/sd
/dev/sda1 on /boot type ext4 (rw,relatime)
/dev/sdb1 on /mnt/usb type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
grep sd /etc/mtab
/dev/sda1 /boot ext4 rw,relatime 0 0
/dev/sdb1 /mnt/usb vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro 0 0
grep sd /proc/mounts
/dev/sda1 /boot ext4 rw,relatime 0 0
/dev/sdb1 /mnt/usb vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro 0 0
ls /mnt/usb
BaseOS
TRANS.TBL
Torque_Kernel
images
ldlinux.c32
ldlinux.sys
...
但是,从 shell 来看,没有任何信息显示设备已安装:
# grep sd /etc/mtab
/dev/sda1 /boot ext4 rw,relatime 0 0
# grep sd /proc/mounts
/dev/sda1 /boot ext4 rw,relatime 0 0
# mount | grep sd
/dev/sda1 on /boot type ext4 (rw,relatime)
# ls /mnt/usb
#
我不明白...登录到新的 shell 也不会改变任何东西。
- Centos 8 内核 4.18.0-147.el8.x86_64
- SELinux 已禁用
- PHP 7.2.11
编辑我
更多发现:
- 仅当命令(通过
/proc/mount
、/etc/mtab
或mount
命令)也在 apache 中运行时,通过 apache 安装的卷才可见 - 安装在 shell 中的卷对于 shell 或通过 httpd 执行的相同命令都是可见的。
编辑二
根据 Philip Couling 的信息,它似乎php-fpm
已经在运行:
$ ps aux | grep php
root 1292 0.0 0.2 240252 22512 ? Ss Jul02 0:04 php-fpm: master process (/etc/php-fpm.conf)
apache 1484 0.0 0.2 255256 17648 ? S Jul02 0:14 php-fpm: pool www
apache 1485 0.0 0.2 255256 17656 ? S Jul02 0:14 php-fpm: pool www
apache 1486 0.0 0.2 255256 17716 ? S Jul02 0:14 php-fpm: pool www
apache 1487 0.0 0.2 255256 17660 ? S Jul02 0:14 php-fpm: pool www
apache 1488 0.0 0.2 255256 17648 ? S Jul02 0:14 php-fpm: pool www
apache 3113 0.0 0.2 255268 17748 ? S Jul02 0:14 php-fpm: pool www
apache 6214 0.0 0.2 255256 17752 ? S Jul02 0:14 php-fpm: pool www
apache 8697 0.0 0.2 255256 17692 ? S Jul02 0:13 php-fpm: pool www
似乎没有什么感兴趣的/etc/php-fpm.conf
或/etc/php-fpm.conf.d/*
答案1
根据 jsbillings 的说法,这听起来像是 apache(和 PHP)正在挂载命名空间内运行。
您可以尝试将 PHP 作为它自己的服务器运行php-fpm。这可以通过 yum 获得,并且网上有许多关于设置此功能的教程。 注意我不确定 Centos 的 php-fpm yum 包是否也放置在挂载命名空间中,所以我不能保证这会起作用。
或者,如果您无法找到一种方法[或不想]运行 PHP 而不将其放入安装命名空间中,那么您可以使用“突破”命名空间恩斯特尔。此命令将允许您在另一个进程的挂载命名空间内运行另一个命令。
命令行应与根进程 (pid 1) 在同一命名空间中运行。因此,在命令行的命名空间中执行命令应该很简单:
function runCmd($cmd)
{
print "$cmd<br />\n";
exec("nsenter -mt 1 $cmd", $lines);
foreach($lines as $l)
{
print "$l<br />\n";
}
print "<br />\n";
}
笔记: 以这种方式安装意味着新的安装可以在命令行上使用,但不能直接在 PHP 进程中使用。