以编程方式运行时 mdadm 不一致

以编程方式运行时 mdadm 不一致

更新#1:

我只是进行了额外的测试,编写了一个 shell 脚本(.sh、#!/bin/bash)和一个由 php 的 cli 执行的 php 脚本。

巴什有效。

似乎不是 Apache 的 HTTP 上下文,而是 PHP 本身导致了问题。因为php raider.php从 root 的 shell 进行简单的运行会遇到最初提到的两个相同的问题。


我正在构建一个带有 WebOS 的设备。 WebOS 托管在 Apache 上,作为http:http.由于 WebOS 需要访问操作系统(root),因此设置了 sudoers - 以允许使用httpNOPASSWD 的 ALL。

请不要对以 root 身份运行的进程进行教育 - 环境是受控的,并且已经工作了 2 年,发货了 40 多个设备,没有报告任何问题。

php命令由(Apache 的 mod_php5)proc_open通过 HTTP 请求上下文运行。

每个命令似乎都工作正常,除了mdadm --create.当我尝试创建阵列时,会出现随机结果,具体取决于我选择创建的 RAID 级别。

以前我有过一个命名空间问题,但现在情况已不再是这样了。在一些操作系统更新后,问题开始出现(不知道具体什么时候,这是旧版本的 WebOS 无法工作,必须在最近提出,显然需要修复 - 有还有一个可以正常工作的新版本(它有不同的命令执行周期))。

我正在使用mdadm_udevinitramfs 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尚未更新它的分区表。

显然,之后的下一个命令partprobemdadm --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 情况下却创建了符号链接。我根本无法理解如何推动准备工作以防止符号链接创建......

相关内容