看到“存储空间损毁”这六个字,玩黑群晖的人基本都懂那种心里一沉的感觉。我前阵子就亲手把一台双盘RAID1的黑群晖救回来了,全程靠SSH一条一条敲命令,没靠群晖图形界面。先说结论:只要硬盘没有物理性死亡,数据分区本身没有被完全写花,这套手动重建RAID1的流程成功率相当高。接下来我会把判断阵列状态、确认盘符、降级移除故障盘、复制分区表、重新加入新盘到等待同步完成的整条链路掰开讲清楚。适合遇到“存储空间损毁”提示的黑群晖用户、NAS维护者,以及所有想搞明白Linux mdraid底层逻辑的人参考。照着操作前,先把重要数据备份好,别指望教程能帮你兜底。
1. 故障分析:先从“存储空间损毁”说起
1.1 群晖RAID1的底层结构:mdraid与分区布局
群晖的RAID1,从底层看就是Linux标准的mdraid。你执行的所有操作,本质都是在跟mdadm打交道,群晖图形界面只是给mdadm包了一层皮。DSM会把每块硬盘划分成几个分区:第一个分区用于引导相关,几百MB到几个GB;第二个分区是系统核心;第三个分区才是用户数据。以最常见的双盘安装为例,两块硬盘的p1组成md0,p2组成md1,p3组成md2。你看到的“存储空间1”,一般就挂在/dev/md2上。
之所以要理解这层结构,是因为当系统提示“存储空间损毁”时,可能是md2出了问题,也可能是md0/md1连带导致DSM判断异常。只有先识别是哪一层坏了,修复才精准。我见过有人在GUI里对着“存储空间1”折腾半天,其实真正掉的是系统分区所在的md1,数据分区还活着。这种“找错病灶”的操作,在SSH里扫一眼/proc/mdstat就能避免。
1.2 “存储空间损毁”是到底怎么发生的
先说两个容易混淆的状态:“存储空间降级”和“存储空间损毁”。降级意味着阵列里还有一块盘在正常工作,系统仍然能读写,只是冗余没有了,此时存储管理器会提示“修复”,换上新盘就能自动重建。损毁则往往是双盘同时掉线、阵列元数据损坏,或者其中一块盘掉线时另一块也大面积报错,导致md设备直接进入inactive状态。
触发损毁的原因,我见过的主要有三类:一是断电,尤其是异常断电,RAID1写缓存里的元数据来不及落盘;二是SATA线松动或背板接触不良,一块盘突然从总线上消失,阵列标记为degraded,长时间不处理,第二块盘出坏道后整体崩溃;三是硬盘本身物理坏道扩散,SMART报警后没有及时换盘。从DSM界面的表现来看,损毁状态下存储管理器可能显示“存储空间x损毁”,并且修复按钮是灰的,或者点修复之后几秒钟又弹回原样。这并不代表数据没了,很多时候只是阵列层的元数据不一致,导致系统不敢自动挂载。这时候图形界面能做的很有限,SSH才能看到真实状态。
1.3 什么时候必须上SSH手动操作
三种典型场景:
- 第一种,GUI点击修复失败,一直提示类似“无法修复存储空间”。
- 第二种,系统启动后存储空间没自动挂载,但磁盘都还在。
- 第三种,你需要把阵列拆开重新组装,比如换引导、换主板后阵列识别不全。
出现这些情况,手动用mdadm反而更直接。你能清楚看到每个md设备的状态、每个成员盘是否在线,也能自己决定是先保住单盘数据,还是强制启动阵列。当然,手动操作的前提是理解每一步在干什么,不然乱敲命令比不修更容易搞坏数据。这也是我写这篇教程的初衷:把底层逻辑讲明白,而不是丢给你几条命令让你照抄。
2. SSH登录与阵列状态摸底
2.1 开启SSH并用终端连接群晖
在群晖控制面板里找到“终端机和SNMP”,勾选“启用SSH功能”,端口默认22,设个高强度密码。黑群晖的引导系统基于Linux,所以SSH服务开着就能连。Windows用户推荐Xshell、MobaXterm,或者Bitvise SSH Client,这三款都比较顺手;macOS和Linux直接终端执行ssh。用VS Code的Remote SSH插件也能连,但建议先用纯终端把网络链路确认通,再折腾插件,不然容易分不清是SSH问题还是插件问题。
连接命令:
ssh admin@192.168.1.100登录后执行sudo -i把权限提到root,后面所有mdadm命令都必须在root身份下跑。注意:群晖默认不允许root远程登录,都是先普通用户登录再提权。如果你习惯免密登录,可以把本地公钥加到群晖的/root/.ssh/authorized_keys里。有些引导版本中,authorized_keys权限必须设置为600,目录700,否则SSH会拒绝。这一点我踩过坑。
要是连接不上,先ping一下IP,再用telnet 192.168.1.100 22或者nc -vz 192.168.1.100 22确认端口通不通,最后检查群晖防火墙有没有放行22端口。很多时候不是SSH服务的问题,而是防火墙把端口挡了。
2.2 三步摸清阵列现状
登录后别急着动手,先用几条命令把家底摸清楚。
第一步,cat /proc/mdstat看阵列状态。这个文件列出了所有软raid设备以及它们的成员盘。正常状态会显示类似md2 : active raid1 sata1p3[0] sata2p3[1],后面还有resync、recovery、reshape等进度字段。如果你看到[U_]或[_U],说明有一块盘掉了。看到inactive,说明阵列没有被激活。
第二步,lsblk看磁盘和分区。群晖里盘符可能是/dev/sata1、/dev/sata2(DSM新版本常见),也可能是/dev/sda、/dev/sdb,用lsblk能看到整盘和分区对应关系。
第三步,df -h看volume挂载点,再mount | grep md看md设备挂在哪里。结合mdadm --detail /dev/md2看阵列成员盘的详细信息。你会发现,群晖界面告诉你的“存储空间损毁”,在命令行里往往只是“md2缺了一个盘”这么简单。
2.3 动手前的备份与记录
无论是什么级别的故障,动阵列之前先想清楚能不能接受最坏结果。理想情况下,健康盘上的数据已经有了备份副本。实在没有备份,我建议先把阵列停掉,单独挂载健康盘看看能不能把关键目录复制出来。
动手前在纸上写清楚这几项:故障盘在哪个槽位、对应的设备名是sata1还是sata2、阵列是md0还是md2、健康盘上的数据分区UUID是什么。写下来不是多此一举,我见过太多人盯着终端敲了半小时,结果把盘符搞反,把好盘拔了,最后数据全丢。这一步怎么强调都不为过。
3. 手动重建RAID1的完整操作流程
3.1 第一步:把故障盘从阵列中降级并移除
假设你已经确定故障盘是/dev/sata2p3,这个分区是数据分区md2的成员。第一件事是告诉阵列:这块盘我不再信任了。
mdadm --manage /dev/md2 --fail /dev/sata2p3 mdadm --manage /dev/md2 --remove /dev/sata2p3--fail会把盘标记为failed,--remove把它从阵列里摘出去。执行之后cat /proc/mdstat,应该只看到sata1p3[0]在干活,阵列状态变成degraded,但系统还能正常读写。
有几个常见情况要注意。如果盘是突然掉线,系统可能已经自动把它标记为failed,你直接remove即可。如果mdadm提示设备不存在,说明Linux已经彻底不认得这个设备,那就别纠结,直接从物理上拔盘。如果阵列整体处于inactive,这一步要先解决,我放在后面问题汇总里讲。总之,先让阵列在单盘模式下稳定运行,这是后续所有操作的前提。
3.2 第二步:物理换盘与分区表复制
移除故障盘之后,把机箱断电,拆下故障盘,换上同容量的新盘,重新开机。除非你确定阵列处于degraded状态且背板支持热插拔,否则别带电拔盘。
新盘不需要初始化文件系统。群晖RAID1里的用户文件系统建立在md设备上,不是建立在单硬盘分区上的。你真正要做的,是让新盘的盘面结构和原先故障盘一样,分区数量、分区边界、分区大小完全一致。最省事的办法是拿健康盘的分区表直接复制过来。
假设健康盘是/dev/sata1,新盘是/dev/sata2,执行:
sfdisk -d /dev/sata1 > /tmp/sata1.txt sed -i 's/sata1/sata2/g' /tmp/sata1.txt sfdisk /dev/sata2 < /tmp/sata1.txtsfdisk -d导出的分区表文件里有一行device: /dev/sata1,用sed替换一下更保险。执行完后,让内核重新读取分区表:
blockdev --rereadpt /dev/sata2再用lsblk确认新盘的p1、p2、p3都分出来了。如果你用的黑群晖引导环境里没有sfdisk,只有fdisk,也可以手动建分区,但一定要对着健康盘的分区起始扇区来,不能凭感觉。
3.3 第三步:把新盘加入阵列触发重建
分区就绪之后,把新盘的数据分区挂到阵列里:
mdadm --manage /dev/md2 --add /dev/sata2p3如果之前这块盘或者分区上残留了别的md超级块,add会报错,提示device or resource busy,或者干脆add不进去。解决办法是先把超级块清零:
mdadm --zero-superblock /dev/sata2p3然后再add。add成功之后,内核会自动发现“这是RAID1缺少的成员”,开始resync。这个过程不用你手动触发,内核会在几秒内自动开始。如果没开始,执行mdadm --detail /dev/md2看看状态,或者确认一下内核日志dmesg | tail。
这里有个细节:群晖会同时有md0、md1、md2,如果系统提示你“系统分区”也有问题,需要按同样的流程依次修复,先修系统相关的小阵列,再修数据阵列。一般情况下先保证md2挂载恢复,用户数据优先。
3.4 第四步:等待同步并校验文件系统
执行完add,马上cat /proc/mdstat,你会看到类似:
md2 : active raid1 sata2p3[1] sata1p3[0] [====>....] resync = 24.4% (xxx/xxx) finish=...这说明重建已经在跑。等resync到100%,再用mdadm --detail /dev/md2确认两个设备状态都正常。
接下来校验文件系统。群晖默认的文件系统是btrfs,重启后系统大概率会自动挂载。如果没挂载,先执行:
btrfs device scan然后尝试挂载:
mount /dev/md2 /mnt或者挂载时加degraded参数,适合只有单盘能挂载的场合:
mount -o degraded /dev/md2 /mnt如果是ext4,用fsck -f /dev/md2。全部正常后,回到DSM图形界面刷新存储管理器,存储空间应该变成“正常”。这里提醒一句:重建完成后别立刻往里面塞大量数据,先让系统跑一两天,观察有没有新的IO错误冒出来。
4. 重建期间的监控与系统保护
4.1 看进度与判断重建速度
重建监控的核心就一个文件:/proc/mdstat。它会实时显示resync的百分比和剩余量,也会显示是哪个md设备在同步。想知道更详细的信息,用mdadm --detail /dev/md2,里面会列出rebuild/resync状态、每个成员盘的健康状态。
同步速度不是一个固定值,取决于总线带宽、硬盘持续读写速度和CPU占用。常见的SATA机械盘重建,大概在80-150MB/s之间;SSD阵列会快很多,200MB/s以上。比如一个2TB数据分区,实际有效数据可能只有几百GB,但因为RAID1是全盘镜像同步,重建时间通常按整盘容量估算。你可以用剩余MB数除以当前速度,大致算出还要多久。
内核也提供了速度限制参数,在/proc/sys/dev/raid/speed_limit_min和speed_limit_max。默认min是1000KB/s,max很多系统设成200000KB/s。如果你发现重建被限速了,可以临时拉高:
echo 100000 > /proc/sys/dev/raid/speed_limit_min echo 400000 > /proc/sys/dev/raid/speed_limit_max注意这只是临时调整,重启恢复默认。正常情况下不建议动,除非你确认当前速度低是因为限速而不是硬盘自身太慢。
4.2 重建期间千万不要做的事
- 不要重启NAS。重建没完成就重启,新盘可能已经从阵列里摘出去,或者resync从头再来一次,极端情况下阵列变成inactive。
- 不要往阵列里疯狂写数据。虽然RAID1重建时系统还可以读写,但高负载会拖慢同步,也会放大IO错误概率。最好暂停下载任务、视频转码等重负载服务。
- 不要去动另一块健康盘。有的人嫌健康盘响应慢,想去摸摸它是不是坏了,结果一不小心把盘从阵列里手动fail了,那就真变成裸奔了。
- 注意散热。机械盘持续读写一两个小时,机箱风扇不够的话温度能飙到50度以上,高温环境下重建容易诱发新坏道。机箱如果小,把盖板打开用个风扇直吹,都是有效的土办法。
- 别在重建期间改阵列结构,比如加盘、换RAID级别、扩容。这些操作要等同步完成、存储管理器确认正常之后再说。
4.3 理解超级块,为什么新盘要清掉旧数据
mdadm会在每一块成员盘上写超级块,记录阵列的UUID、RAID级别、成员顺序等元数据。当你往阵列里加一块之前用过的盘,如果不把这块盘上的旧超级块清掉,内核可能误以为它是另一个阵列的成员,拒绝添加。mdadm --zero-superblock /dev/sata2p3就是把这个位置的元数据擦掉,让它变成一张“白盘”。
另外,群晖的RAID元数据布局和标准Linux略有差别,但底层还是在/dev/sataXpY上写超级块。这就是为什么你手动add之前必须先确认分区编号是否和健康盘一致。分错区、用错盘符,轻则重建失败,重则把另一块正常盘的数据卷进新的resync里,数据就真没了。
5. 典型故障与排查经验
5.1 问题一:阵列变成inactive怎么办
阵列inactive是最让人紧张的状态,因为它意味着系统根本不把md设备当可用设备挂载。现象通常是/proc/mdstat里显示md2 : inactive sata1p3[1],或者干脆没有md2条目。
处理思路是先把阵列手动组装起来:
mdadm --stop /dev/md2 mdadm --assemble /dev/md2 /dev/sata1p3 /dev/sata2p3如果只有一块盘健康,可以只写健康盘的成员:
mdadm --assemble --force /dev/md2 /dev/sata1p3--force会强制使用剩余成员启动阵列,在确认这块盘数据基本正常的情况下可以试。启动后立刻把重要数据拷贝出来。这种能救,但救完别指望阵列还能继续正常服役,该换盘换盘,该备份备份。
5.2 问题二:add新盘时报capacity too small
如果新盘容量比阵列记录的最小成员容量还小,mdadm会直接拒绝,提示capacity too small。比如原来的故障盘是一块1TB盘,你换了一块800GB的盘,分区表复制的起点和终点不一样,阵列认为是有效容量不足。要么换回规格相同的盘,要么把分区规划成不超过阵列认可边界。这种提示不是数据损坏,只是容量校验没过,别慌。
还有一种add失败的常见原因是device or resource busy,说明分区正被别的设备占用。这种情况先看cat /proc/mdstat确认它没被别的md设备占用,再用lsblk确认没有挂载点,必要时直接重启再执行add。
5.3 问题三:重建完成后存储空间仍然显示损毁
阵列resync到100%不代表DSM界面就一定恢复“正常”。因为群晖的存储空间还依赖文件系统层,尤其是btrfs,如果不一致,DSM依然会报警。
我的排查顺序是:
- 先确认底层阵列健康:
mdadm --detail /dev/md2,两个成员都应该是active sync。 - 再看文件系统能不能挂载:
mount /dev/md2 /mnt,失败就btrfs device scan后再试。 - 如果btrfs报错,先
btrfs filesystem check /dev/md2,按提示修复。群晖里运行这些命令要小心,最好先备份btrfs元数据。 - 最后重启NAS,让DSM重新扫描一遍,通常到这一步存储管理器就恢复“正常”了。
还有一种是系统分区md1重建不完整,导致DSM对存储管理器报出错误的不可用判断,这种需要把md1也加到阵列里补同步。
5.4 问题四:盘符漂移
换盘之后,BIOS、主板端口的枚举顺序变化,/dev/sata1和/dev/sata2的对应关系可能对调。严格来说Linux在枚举时按端口命名,不同引导版本表现不一样,但只要你换了盘,就一定要用分区UUID确认身份,不要只看盘符顺序。
用lsblk -f /dev/sata1,或者blkid /dev/sata1p3,拿到每个分区真实UUID。健康盘复制过来的分区表和原盘一致,UUID也会被复制,但md超级块里的UUID是阵列自己的,指向md2。物理盘的身份可以结合smartctl -i /dev/sata1查看序列号来确认。一句话:以序列号和UUID为准,别信盘符。
5.5 常见问题速查表
| 现象 | 可能原因 | 排查命令 | 处理建议 |
|---|---|---|---|
| 存储空间损毁提示 | 阵列降级或inactive | cat /proc/mdstat,mdadm --detail /dev/md2 | 先组装/启动阵列,再换盘重建 |
| add报resource busy | 分区被占用或残留superblock | lsblk,cat /proc/mdstat | 清空超级块后重新add |
| add报capacity too small | 新盘容量不足 | lsblk查看容量 | 换同规格盘,或调整分区边界 |
| 重建很慢或卡住 | 硬盘坏道、限速、高负载 | smartctl -a /dev/sataX,iostat -x 1 | 检测健康盘,暂停负载,临时调高限速 |
| 重建完仍报警 | 文件系统btrfs错误 | btrfs filesystem check /dev/md2 | 备份元数据后修复,必要时degraded挂载导出数据 |
| 掉盘后开机卡引导 | 系统分区md0/md1损坏 | cat /proc/mdstat | 单盘启动后拷贝数据,重建系统分区 |
修完这一次,我对RAID1的心态反而更敬畏了。它防的是单块盘故障,不是备份;它能扛住一次坏道扩散,但扛不住你两年不备份加上机箱里还有一根劣质SATA线。手动重建阵列这套流程,说白了就五步:确认掉盘、fail掉、remove掉、换完盘add回来、等resync。真正难的不是命令,而是遇到问题时能不能保持冷静,不把好盘拿去陪葬。
最后再分享一个我自己的习惯:阵列恢复正常之后,顺手把mdadm --detail --scan的输出备份一份。下次再碰到类似问题,直接照着重建,能省不少时间。希望这篇东西能让你在SSH窗口前少慌几分钟,多保住几TB数据。