更新#1:
我只是进行了额外的测试,编写了一个 shell 脚本(.sh、#!/bin/bash)和一个由 php 的 cli 执行的 php 脚本。
巴什有效。
似乎不是 Apache 的 HTTP 上下文,而是 PHP 本身导致了问题。因为php raider.php
从 root 的 shell 进行简单的运行会遇到最初提到的两个相同的问题。
我正在构建一个带有 WebOS 的设备。 WebOS 托管在 Apache 上,作为http:http
.由于 WebOS 需要访问操作系统(root),因此设置了 sudoers - 以允许使用http
NOPASSWD 的 ALL。
请不要对以 root 身份运行的进程进行教育 - 环境是受控的,并且已经工作了 2 年,发货了 40 多个设备,没有报告任何问题。
php
命令由(Apache 的 mod_php5)proc_open
通过 HTTP 请求上下文运行。
每个命令似乎都工作正常,除了mdadm --create
.当我尝试创建阵列时,会出现随机结果,具体取决于我选择创建的 RAID 级别。
以前我有过一个命名空间问题,但现在情况已不再是这样了。在一些操作系统更新后,问题开始出现(不知道具体什么时候,这是旧版本的 WebOS 无法工作,必须在最近提出,显然需要修复 - 有还有一个可以正常工作的新版本(它有不同的命令执行周期))。
我正在使用mdadm_udev
initramfs hook 在启动时组装 RAID。我留空了/etc/mdadm.conf
,因为mdadm_udev
似乎是根据 RAID 的元数据正确组装的。但唯一的问题是,当它组装它们时,它会根据<hostname>:<raidname>
.
由于上面的问题,我正在使用mdadm --create /dev/md/<hostname>:stoneshare ...
,无论用户是什么(非 root 用户作为 sudo 运行并成功),它似乎都可以从 CLI 运行良好,但在通过 HTTP 上下文运行时会出现问题。
场景 #1,RAID0:
<?php
$command = sprintf('sudo mdadm --create /dev/md/%s:stoneshare --level 0 --raid-devices 2 /dev/sdb1 /dev/sdc1');
proc_open($command, /* ... */, /* ... */);
RAID 已创建,但是,在 CLI 启用 RAID/dev/md127
并将符号链接到 的情况下/dev/md/<hostname>:<sharename>
,通过运行上述脚本,我最终/dev/md127
没有链接:
[root@stone ~]# mdadm --detail --scan
ARRAY /dev/md127 metadata=1.2 name=stone:stoneshare UUID=7329e458:96be442a:84f616d8:fd4ba42e
[root@stone ~]# ls -la /dev/md*
brw-rw---- 1 root disk 9, 127 Jul 30 11:48 /dev/md127
场景#2,RAID1:
<?php
$command = sprintf('sudo mdadm --create /dev/md/%s:stoneshare --level 1 --assume-clean --raid-devices 2 /dev/sdb1 /dev/sdc1');
proc_open($command, /* ... */, /* ... */);
查看:
[root@stone ~]# mdadm --detail --scan
ARRAY /dev/md/stone:stoneshare metadata=1.2 name=stone:stoneshare UUID=7329e458:96be442a:84f616d8:fd4ba42e
[root@stone ~]# ls -la /dev/md*
brw-rw---- 1 root disk 9, 127 Jul 30 11:48 /dev/md127
/dev/md:
total 0
drwxr-xr-x 2 root root 60 Jul 30 12:17 .
drwxr-xr-x 19 root root 3080 Jul 30 12:17 ..
lrwxrwxrwx 1 root root 10 Jul 30 12:17 stone:stoneshare -> /dev/md127
奇怪的是,虽然创建了符号链接,但存在一个不同的问题 - 在创建 RAID 时,随机/dev/sdb1
或/dev/sdc1
自动标记为错误。 RAID 已创建并启动,但正在使用 1 个驱动器运行。有时,两个驱动器都没有被标记为有故障,并且创建 RAID 时完全没有问题。
我精心挑选了我发现的设备故障的相关信息:
[root@stone ~]# journalctl -xb
Jul 30 11:39:43 stone kernel: md: bind<sdb1>
Jul 30 11:39:43 stone kernel: md: bind<sdc1>
Jul 30 11:39:43 stone kernel: md/raid1:md127: active with 2 out of 2 mirrors
Jul 30 11:39:43 stone kernel: created bitmap (8 pages) for device md127
Jul 30 11:39:43 stone kernel: md127: bitmap initialized from disk: read 1 pages, set 14903 of 14903 bits
Jul 30 11:39:43 stone kernel: md127: detected capacity change from 0 to 1000068874240
Jul 30 11:39:43 stone kernel: md127: unknown partition table
Jul 30 11:39:43 stone systemd[1]: Starting MD array monitor...
Jul 30 11:39:43 stone systemd[1]: About to execute: /usr/lib/systemd/scripts/mdadm_env.sh
Jul 30 11:39:43 stone systemd[1]: Forked /usr/lib/systemd/scripts/mdadm_env.sh as 457
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service changed failed -> start-pre
Jul 30 11:39:43 stone systemd[457]: Executing: /usr/lib/systemd/scripts/mdadm_env.sh
Jul 30 11:39:43 stone systemd[457]: Failed at step EXEC spawning /usr/lib/systemd/scripts/mdadm_env.sh: No such file or directory
Jul 30 11:39:43 stone systemd[1]: Received SIGCHLD from PID 457 ((m_env.sh)).
Jul 30 11:39:43 stone systemd[1]: Child 457 ((m_env.sh)) died (code=exited, status=203/EXEC)
Jul 30 11:39:43 stone systemd[1]: Child 457 belongs to mdmonitor.service
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service: control process exited, code=exited status=203
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service got final SIGCHLD for state start-pre
Jul 30 11:39:43 stone systemd[1]: About to execute: /sbin/mdadm --monitor $MDADM_MONITOR_ARGS
Jul 30 11:39:43 stone systemd[1]: Forked /sbin/mdadm as 460
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service changed start-pre -> running
Jul 30 11:39:43 stone systemd[1]: Job mdmonitor.service/start finished, result=done
Jul 30 11:39:43 stone systemd[1]: Started MD array monitor.
Jul 30 11:39:43 stone kernel: md: md127 still in use.
Jul 30 11:39:43 stone kernel: md/raid1:md127: Disk failure on sdb1, disabling device.
md/raid1:md127: Operation continuing on 1 devices.
Jul 30 11:39:43 stone mdadm[460]: mdadm: No mail address or alert command - not monitoring.
Jul 30 11:39:43 stone systemd[460]: Executing: /sbin/mdadm --monitor --scan
Jul 30 11:39:43 stone systemd[1]: Received SIGCHLD from PID 460 (mdadm).
Jul 30 11:39:43 stone systemd[1]: Child 460 (mdadm) died (code=exited, status=1/FAILURE)
Jul 30 11:39:43 stone systemd[1]: Child 460 belongs to mdmonitor.service
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service: main process exited, code=exited, status=1/FAILURE
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service changed running -> failed
Jul 30 11:39:43 stone systemd[1]: Unit mdmonitor.service entered failed state.
Jul 30 11:39:43 stone systemd[1]: mdmonitor.service: cgroup is empty
Jul 30 11:39:43 stone kernel: RAID1 conf printout:
Jul 30 11:39:43 stone kernel: --- wd:1 rd:2
Jul 30 11:39:43 stone kernel: disk 0, wo:1, o:0, dev:sdb1
Jul 30 11:39:43 stone kernel: disk 1, wo:0, o:1, dev:sdc1
Jul 30 11:39:43 stone systemd[1]: Got disconnect on private connection.
Jul 30 11:39:43 stone kernel: RAID1 conf printout:
Jul 30 11:39:43 stone kernel: --- wd:1 rd:2
Jul 30 11:39:43 stone kernel: disk 1, wo:0, o:1, dev:sdc1
Jul 30 11:39:43 stone kernel: md: unbind<sdb1>
Jul 30 11:39:43 stone kernel: md: export_rdev(sdb1)
我想,我怀疑这mdmonitor
对于创建 RAID 是否至关重要。
从 CLI 运行时,两个 RAID 都完美组装,没有遇到任何问题。
根据 SMART 的数据,驱动器是健康的。
实际上,UUID 并不相等,我只是根据单个 RAID 制作了示例。
我在这里做错了什么,导致了这种不一致?
答案1
TL;博士。
我发现问题出在哪里了!我sleep
在一些分区任务之间需要一些时间。显然我偶然发现了并发问题。
深入:
看起来当一个进程完成时,并不意味着内核已经完成了它在进程中的角色(以防内核必须在给定进程之后执行某些操作)。就我而言,这就是分区 - 显然,我开始得mdadm --create
太早了,当时内核还没有更新一些分区更改。是的,我有partprobe
介于两者之间的情况,但看起来它也没有意识到变化。
我开始使用 shell 脚本、cli php 脚本、Web 脚本进行调试,直到我偶然发现:
[root@stone /] parted -s /dev/sdb mklabel gpt unit GB mkpart primary 0 100%
[root@stone /] parted -s /dev/sdc mklabel gpt unit GB mkpart primary 0 100%
[root@stone /] partprobe
[root@stone /] lsblk
sda 8:0 0 55.9G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 500M 0 part /boot/efi
├─sda3 8:3 0 500M 0 part [SWAP]
└─sda4 8:4 0 54.9G 0 part /
sdb 8:16 0 931.5G 0 disk
└─sdb1 8:17 0 931.5G 0 part
sdc 8:32 0 931.5G 0 disk
当命令执行时没有间隔,让 CPU 尽可能快地处理它们 - 我注意到/dev/sdc
尚未更新它的分区表。
显然,之后的下一个命令partprobe
是mdadm --create
,它开始时没有对分区表进行任何更改,从而导致奇怪的行为。
可能我的观察和假设是完全错误的,但至少这是我可以为自己逻辑地解释情况的方式。
是的,解决方法是sleep
在调用之间添加:
[root@stone /] parted -s /dev/sdb mklabel gpt unit GB mkpart primary 0 100%
[root@stone /] parted -s /dev/sdc mklabel gpt unit GB mkpart primary 0 100%
[root@stone /] sleep 1
[root@stone /] partprobe
[root@stone /] sleep 1
[root@stone /] lsblk
sda 8:0 0 55.9G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 500M 0 part /boot/efi
├─sda3 8:3 0 500M 0 part [SWAP]
└─sda4 8:4 0 54.9G 0 part /
sdb 8:16 0 931.5G 0 disk
└─sdb1 8:17 0 931.5G 0 part
sdc 8:32 0 931.5G 0 disk
这解决了问题。
但最后,我仍然找不到一个逻辑解释来解释为什么在 RAID0 情况下它没有创建符号链接,而在 RAID1 情况下却创建了符号链接。我根本无法理解如何推动准备工作以防止符号链接创建......