1. 新硬盘装上去之后,系统里为什么看不到可用空间
先说个我经常遇到的场景:某同学给一台Linux服务器加了一块新数据盘,开机进系统后,df -h一看,容量没变化;再打开“计算机”之类的图形界面找一圈,也没看到新盘符。他第一反应是硬盘坏了或者主板没认出来,折腾半天,最后发现其实系统早就看到了设备,只是这块盘既没有分区、也没有文件系统,更没有被挂载到任何目录下,所以它的容量对操作系统来说就像不存在一样。
这就是本篇“Linux硬盘分区挂载”要解决的核心问题:把一块物理硬盘变成系统里真正可用的存储空间。整个过程可以拆成三段——认盘、分区格式化、挂载到目录。你要做的不是背命令,而是理解每一步在干什么,这样以后不论系统提示什么异常,你都能自己判断是哪一步出了岔子。
这个系列面向的读者主要是三类人:刚接触Linux想把手头机器盘清楚的初学者;公司里要接管服务器、需要给机器加容量的小运维;以及做开发时候需要在虚拟机里挂一块新虚拟磁盘做实验的同学。我们假设你已经能进到命令行,并且以root权限或者sudo方式执行命令,下面所有操作我都按这个前提来写。
1.1 设备不是你想的C盘D盘,而是/dev下的文件
Windows用户习惯把硬盘看成“C盘”“D盘”,但在Linux里,硬盘设备本身被抽象成了/dev目录下的一个特殊文件。刚接触的人会觉得这个设计很绕,可一旦你接受了“设备也是文件”的哲学,后面的分区、挂载、卸载就都好理解了。
传统的SATA盘、USB盘在系统里通常显示成/dev/sda、/dev/sdb这种名字,字母从a开始往后排,代表物理上的识别顺序。如果你的机器装的是NVMe固态,设备名会变成/dev/nvme0n1这种格式,名字里的0代表nvme控制器序号,n1代表命名空间下的块设备,它的分区则是/dev/nvme0n1p1,注意这里的“p1”和SATA盘那种“sda1”写法不一样,很多人第一次看到都愣一下。
我见过不少新手对/dev/sda和/dev/sda1的区别搞不清楚。简单说,sda是整块盘,sda1是这块盘上的第一个分区。往整块盘上直接写文件系统不是不行,但除非是特殊场景(比如某些云盘的整块直挂),我都不建议,原因后面讲分区的时候会解释。你只要记住:认盘看sda,分区看sda1。
1.2 用lsblk和fdisk把硬盘的“出生状态”摸清楚
我拿到一台陌生机器,第一步永远是敲lsblk,这个命令比df -h更适合看设备结构。它不像df那样只显示已经挂载的文件系统,而是把所有块设备以及它们之间的层级关系完整列出来,就像给硬盘做了一次全身体检报告。
lsblk输出大概长这样(根据实际环境会略有差异):
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 238G 0 disk ├─sda1 8:1 0 600M 0 part /boot/efi ├─sda2 8:2 0 1G 0 part /boot └─sda3 8:3 0 236.4G 0 part / sdb 8:16 0 465G 0 disk └─sdb1 8:17 0 465G 0 part /data注意看最后一列MOUNTPOINT,这就是挂载点的意思。新加的盘如果从来没操作过,你会看到类似于sdb这样的裸设备,它下面没有分区子项,MOUNTPOINT列也是空的。这就已经说明问题不是“系统没识别”,而是“盘还没进入可用的存储体系”。
如果lsblk里压根没看到这块盘,那才需要考虑硬件层面的问题。比如先确认接口是不是插好了、供电有没有接上,然后可以用dmesg | grep sd看内核有没有在启动或者热插拔时发现新设备。遇到虚拟化平台还要检查是不是忘了在虚拟机设置里把磁盘挂载给这台机器,这个坑在云服务器和虚拟化环境里尤其常见,稍后单说。
1.3 那种“识别不出来”的硬盘到底怎么回事
先说结论:大多数“识别不出来”都是假象,盘实际上被看见了,只是没有分区没有文件系统,所以你在文件管理器里看不到任何容量。真正系统层面看不见的情况,通常集中在三个原因。
第一是热插拔场景下的驱动或总线问题,SATA盘的顺序在热插拔后可能从sda挪到sdb,而fstab里如果写死了旧设备名就会出现开机挂载错位;第二是分区表本身损坏,这种情况fdisk -l会直接报错说找不到有效的分区表;第三是虚拟化环境忘记挂载磁盘,比如某云控制台新增了数据盘,但实例内部要等操作系统重新扫描总线才能看到。
判断“系统到底看没看见”有一个比较可靠的办法,用lsblk和fdisk -l互相验证,前者看的是内核已知的设备树,后者是直接读取磁盘分区表,两个命令都看不到才基本可以确定是物理或者虚拟化层面的问题。如果只是df -h看不到,那多半是接下来要讲的分区与挂载环节还没做。
2. 分区到底是在做什么,用哪个工具更顺手
确认硬盘被系统认出来之后,下一步就是分区。这一步很多教程都是一句话带过,但分区其实是“给硬盘定规则”的过程,规则没定对,后面格式化、挂载都会跟着别扭。
我打个比方。一块新硬盘就像一块还没划分房间的空地。空地本身不能用,你得先在地上画出道路和区域界线,标明哪块是住宅、哪块是仓库、哪块留白,这个“画线”的动作就是分区。MBR和GPT就是两种不同的“画线规范”,而fdisk、parted这些工具就是拿着规范在地上画线的“施工队”。
2.1 MBR和GPT的差异决定了你要不要一路回车
分区表类型直接决定这块盘能支持多大容量、能分多少个区,以及哪些系统能识别。我见过一些老教程还在默认用MBR,新人不假思索照做,结果2TB以上硬盘只有前2TB可用,剩下部分全部浪费,等发现的时候数据已经写进去了,尴尬至极。
MBR(Master Boot Record)是老派规范,分区表放在磁盘最开始的那512字节里,结构简单,兼容性极好,连上世纪的老机器都能认。但它的天花板很明显:单块盘最大只能管理到2TB,而且只允许4个主分区(想多分就得用扩展分区的办法绕)。如果你只是给一台老机器加一块小容量盘当启动盘,MBR完全够用,真的不用纠结。
GPT(GUID Partition Table)是现代规范,也是目前所有新机器、新系统的主流默认。它对容量的支持上限大得多,理论上有多少空间就能用多少空间,分区数量方面标准设计支持到128个,日常完全不会撞到限制。它还在头部之外保留了冗余的分区表备份,容错性也更好。
我给你的选型建议很简单:新装的机器、数据盘、2TB以上的大容量盘,一律用GPT;只有当你明确知道某块老主板或者老系统对MBR有硬性要求时,才回退到MBR。在Linux下用fdisk新版工具分区时,默认就会帮GPT说话,这对新人反而是个保护。
2.2 fdisk交互式操作记录:从新手角度走一遍
很多人怕fdisk是因为它是个交互式工具,进去之后屏幕上全是字母提示,不敢乱按。其实常用的按键一只手数得过来:p打印分区表,n新建分区,d删除分区,w保存退出,q不保存退出。记住这五个就够走完整个流程。
操作前先确认设备名。假设我要给设备/dev/sdb分区:
fdisk /dev/sdb进入交互界面后,按n开始起一个分区。默认会问你是主分区还是扩展分区,新手用GPT的话不会碰到这个问题,直接用默认值。然后会让你输入起始扇区,我建议直接回车用默认值,现在工具默认会按1MiB对齐来设置起始位置,对SSD比较友好,不需要手填一个神秘的数字。结束扇区那里同样可以直接回车表示用满整块盘,或者写+200G这种格式来指定分区大小,灵活性在你手上。
搞定之后按p看一眼分区计划,确认无误再按w写盘。这一步特别重要,因为w一旦执行,分区表就真的写入磁盘了。如果你中途发现自己划错了,按q退出就行,刚才按过的n、d全部作废,磁盘不会有任何改变。这个“w和q的区别”是新手最容易忽略的安全阀。
2.3 parted翻车实录:为什么脚本化方案未必适合新手
新手有另一个常踩的坑就是我图新鲜用了parted,结果被它的操作风格打得措手不及。parted的优势是支持脚本化、能直接在命令行后接参数一步到位,比如:
parted /dev/sdb mklabel gpt parted /dev/sdb mkpart primary ext4 1MiB 100%这两条命令确实能完成从建分区表到划区的全部工作,看起来比fdisk高效得多。但parted对用户输入非常“实诚”,很多操作一旦确认就会立即执行,不存在fdisk那种先草稿后提交的机制。我认识不止一个人用parted时把设备名写错了,本想分区sdb,结果稀里糊涂对正在使用的sda执行了建表命令,那酸爽的滋味我不太想替你体验。
所以我给初学者的建议是:交互式用fdisk,谨慎推进;脚本化用parted,务必确认设备名。如果你正在给生产环境机器加盘,我强烈建议你至少把fdisk流程走完,每一步打印出来的分区计划都跟备份记录核对一遍再提交。这个习惯能救你很多次。
3. 文件系统这一步才是“分区变存储空间”的关键
分区表画完之后,你有了/dev/sdb1这样一个分区设备,但这还不是终点。这时候你去挂载它,系统会直接报错说“unknown filesystem type”,因为分区里还没有组织数据的规则。分区的下一步是创建文件系统,也就是俗称的格式化。
还是拿空地打比方:分区画好了区域界线,但区域内部还是一片荒地,需要你铺设道路、建编号门牌、制定堆放规则,文件系统就是这个“内部规整”的过程。没有文件系统,操作系统不知道数据该怎么存放、怎么索引、怎么清理,所以格式化绝不是可有可无的一步。
3.1 分区表只是地图,文件系统才是数据的组织规则
很多人以为格式化就是“清空数据”,这个理解偏了。格式化更准确地说是“初始化”,它在分区内创建一套数据组织框架。不同的文件系统类型就是不同的组织框架,就像仓库里既有按货架编号管理的,也有按颜色分区的,各有各的玩法。
Linux下常见的文件系统有ext4、xfs、btrfs,还有面向特殊使用场景的vfat、ntfs等。对于一块数据盘,选型主要看用途。ext4是最稳妥的老将,兼容性好、出问题容易恢复,日常文件和普通数据库使用都很不错;xfs在超大规模文件和吞吐性能上更有优势,是不少分布式存储和虚拟化环境的默认选择;btrfs功能丰富,支持快照和压缩,但对使用者的理解能力要求更高,生产环境里不是我的首选。
选择文件系统有个很现实的原则:不要为了“理论上最厉害”去选自己不了解的,选你出问题时最容易找到资料、最可能问得到人的那一个。ext4就是这种“平庸但安心”的选择,xfs则在需要大容量高吞吐时值得考虑。
3.2 ext4和xfs怎么选:别被“性能最好”带偏
我把常用文件系统放在一张表里对照看,这样的差异会非常直观:
| 文件系统 | 特点 | 适合场景 | 注意事项 |
|---|---|---|---|
| ext4 | 老牌稳健,工具链成熟,排查资料多 | 普通数据盘、数据库、虚拟机镜像 | 最大单文件16TB,单分区上限可达1EB(实际受工具限制) |
| xfs | 大文件性能好,扩展性强,适合大容量 | 海量大文件存储、备份目录、虚拟化平台 | 不支持缩容,扩容只能增加 |
| btrfs | 快照、压缩、自愈等高级功能 | 需要快照和子卷特性的高级场景 | 功能多但复杂度高,新手慎入生产 |
| vfat/ntfs | 与Windows交换数据时的兼容选项 | USB移动盘、双系统共享盘 | 权限支持极其有限,不适合装Linux程序 |
我用一段白话帮你做决定:如果是机器上的普通数据盘,ext4几乎不会出错;如果你预期这块盘里以后会堆大量日志、备份、或者虚拟机镜像文件,那xfs更合适;如果只是临时倒腾文件,用vfat也没毛病。
3.3 mkfs命令实操及格式化前需要想清楚的事
创建文件系统的命令格式非常直接:
mkfs.ext4 /dev/sdb1 # 或者 mkfs.xfs /dev/sdb1格式化之前有几件事必须想清楚,这是我最想反复强调的。第一,确认你格式化的目标设备是对的那一个。mkfs执行时不跟你儿女情长,如果你手一抖把设备名写成了正在用的分区,那个分区里的所有数据会瞬间归零,而且这个过程没有回收站。我自己的习惯是格式化前一定要先看一遍lsblk和fdisk -l,设备名、容量、挂载点全部对上才动手,宁可多花三十秒也不要拍脑袋。
第二,确认这个分区未来不会需要缩容。分区规划时如果觉得不确定,我的建议是“宁大勿小”,尤其不要轻易把系统盘和数据盘放在同一个分区里,以后想拆开难度翻倍。用LVM逻辑卷管理当然能缓解这个问题,但那是后面系列文章的内容,这一篇我们先用传统方式把事情跑通。
第三,也是很多教程不提的:格式化操作会消耗时间。小盘几秒搞定,几TB的大盘可能要好几分钟,期间千万不要强制中断。如果你在虚拟机上格式化一块“预分配”的大容量磁盘,时间会更长,别误以为死机了,看进程状态就好。
4. 挂载的底层逻辑:把设备接到目录树上的那一瞬间
分区格式化完之后,设备拥有了一套完整的存储空间,但Linux用户要访问它,还差最后一道手续——挂载。挂载这个词听起来有点玄,其实就是“给这个文件系统找一个门牌号,让它出现在系统目录树的某个位置”。
很多初学者挂载之后就完事了,也不理解为什么要这样做。这里面的底层逻辑其实一句话就能讲透:Linux中没有Windows那种独立的“盘符”,全系统只有一个从根开始的目录树,任何存储设备里的文件系统想被访问,都必须“接入”这棵树的某个目录节点上。那个目录就是挂载点。
4.1 Linux只有一个根目录树,挂载点就是设备的“入口”
如果你进入一个目录后用df -h查看,会发现它显示的是某个分区,这是因为你看到的文件实际存在那个分区的文件系统里。挂载的本质就是告诉系统:从目录/data开始往下的所有子树路径,都由我这份文件系统提供内容。没有挂载,分区里的文件系统只是个封闭空间,只有内核知道它存在,普通程序访问不到。
这个设计解决了一个非常实际的问题:你完全不用担心“系统里有几个盘、每个盘叫什么盘符”,只要挂载点规划合理,用户可以无感地跨设备使用文件。比如/home挂一个大分区、/data挂另一个大分区,对用户来说都只是路径不同而已。
设置挂载点有几个小讲究。目录名最好能体现用途,比如/data用于数据盘、/backup用于备份盘;挂载点目录必须预先创建好,mkdir一下不费劲;尽量别把挂载点建在系统盘的顶层繁忙目录里,避免两个文件系统在同一路径上打架。
4.2 mount命令的完整打开方式
挂载命令的基本结构是:
mount [参数] 设备 挂载点实际操作里,大多数场景只需要指定设备和挂载点,系统会从设备上的文件系统类型自动判断挂载方式:
mkdir -p /data mount /dev/sdb1 /data执行完可以用df -h验证,你会看到/dev/sdb1已经挂在/data下,剩余容量一目了然。有时候还需要加参数,比如只读挂载可以写成:
mount -o ro /dev/sdb1 /data这种只读挂载非常适合备份恢复场景,防止误操作把数据改坏。
这里必须提醒一个所有新手都会犯的错:挂载前要确认挂载点目录是空的。如果目录里原来有子目录和文件,挂载后这些旧文件会被“盖住”,你访问到的全是新分区的内容,而旧文件并没有被删除,只是暂时看不见了。等你解除挂载,它们又会重新出现。这就像在一个房间门口贴了张新图,门开着还是旧房间,但隔着图你只能看到新图的内容。这个机制既能保护数据,也容易让人误以为“文件丢了”。
4.3 挂载参数与性能:noatime为什么是很多人忽略的一行
mount命令的-o参数不只是管读写权限,它直接关系到基础性能。最被我常挂在嘴边的一个参数是noatime。
Linux默认记录文件访问时间(atime),意味着每次读文件都要写一次时间戳。在数据库或日志类高并发读写场景下,这种“读文件还得写磁盘”的行为会产生不必要的IO开销。挂载时加上noatime,就相当于告诉系统“不更新访问时间,别做这笔多余开销”,对性能往往有肉眼可见的改善。对绝大多数数据盘来说,放弃atime并没有实际损失,所以我建议普通数据盘一律加上。
另一个常用参数是nofail,它在上一步fstab场景中更有用,先记下这个名字,下一节细说。还有defaults,它相当于一堆默认选项的组合,包括读写、异步写入、设备允许执行程序等,适合一无所知时先跑起来。
5. 永久挂载:fstab里的每一列都是一个坑
挂载命令执行完,一切看起来都正常了,但你重启一遍机器就会发现,/data目录又空了,设备也没有自动挂载。这是因为 mount 命令只对当前开机周期生效,它不会写进任何持久化配置。想让系统每次启动都自动挂载,就得修改/etc/fstab这个文件。
fstab的全称是File Systems Table,它是系统启动时读取的“挂载清单”。如果你没配置它,重启后就得手动mount,这在日常测试没问题,放到生产环境就是灾难。我见过不少同学辛辛苦苦把数据写进新盘,结果机房断电重启后程序找不到路径,全公司业务报警,原因仅仅是没有写fstab。所以一台正经服务器上的数据盘,是必须要做永久挂载的。
5.1 为什么重启就没了:mount是临时的,fstab才是清单
我把这个过程再掰开一点讲。Linux开机后,内核完成基本初始化,就会去读/etc/fstab文件,把里面登记的每一项设备按照指定路径挂载好。整个过程可以理解成:fstab是一份早餐订单,系统开机那一刻就是厨房开工时间,订单里写了什么,桌面就上什么。你手动敲的 mount 只是临时点了一份餐,吃完(重启)就什么都没了。
所以配置永久挂载的正确姿势是:在/etc/fstab里写清楚“哪个设备、挂到哪、什么文件系统、哪些选项、是否备份、是否自检”,一共六列,缺一不可。
5.2 UUID、设备名与卷标:选谁当身份凭证
写fstab时最关键的决策是用什么来标识“哪个设备”。有三个候选:设备名、UUID、卷标。各自特点我直接列出来:
| 标识方式 | 例子 | 优点 | 缺点 |
|---|---|---|---|
| 设备名 | /dev/sdb1 | 直观,一眼看懂 | 设备顺序可能变化,重启后可能变成sdc1,不稳定 |
| UUID | 2f8e9a5c-... | 全球唯一,只要分区没重建就不会变 | 不直观,需要查 |
| 卷标 | LABEL=data | 有语义,好看 | 卷标可能冲突,且依赖文件系统支持 |
我的建议是默认用UUID。理由很简单:设备名在热插拔、多盘场景下可能乱序,UUID却等于每个文件系统唯一的身份证号,稳定得多。拿到UUID的方法:
blkid /dev/sdb1输出里会直接给出那一串UUID。当然,如果你用的文件系统正好支持卷标,并且你能保证卷标在整个系统里唯一,用它也不是多大的罪过,只是UUID始终是最稳妥的选择。
5.3 fstab六列完全拆解加一个恢复流程
/etc/fstab里每一行都有六列,这里用一行示例拆开讲:
UUID=2f8e9a5c-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data xfs defaults,nofail 0 0第一列是设备标识,这里写UUID;第二列是挂载点,必须是已存在的目录;第三列是文件系统类型,对上了分区格式即可;第四列是挂载选项,多个选项用逗号隔开,我前面说的noatime和nofail都可以放这里;第五列是是否备份,一般写0;第六列是开机时是否做文件系统检查,根分区通常写1,其他数据盘写0或2都行。
这里专门说一下nofail。加了它之后,如果系统启动时发现这个设备不存在,不会卡死等待、也不会报错中断开机流程。这对U盘、可移除设备尤其有用,不然拔掉U盘后重启,系统有可能直接卡在某步等你按ctrl+d。数据盘要不要加nofail见仁见智:有些人觉得数据盘必须存在,失败了就应该停下来让人处理;我个人的倾向是云服务器上默认加,本地物理机视情况而定,但我会先在测试环境验证。
改完fstab后,可以用mount -a让系统重新读取并尝试挂载所有条目,确认配置没有语法错误再重启。如果真的一不小心写错了导致开机卡住,不要慌,进到单用户模式或者用系统安装U盘进入急救模式,把/etc/fstab里出错的那一行注释掉,重启即可。这个恢复流程建议在任意一台测试机上模拟一遍,别等生产事故时第一次练手。
6. 挂载之后还会碰到的事:扩容、换盘与卸载
分区挂载跑通只是开始,真正的坑往往在后续维护里。我见过太多人分区表、文件系统建完之后就不管了,直到磁盘空间不够才发现当初分区划小了、文件系统选型不好改,悔之晚矣。所以把挂载之后的常见操作和坑也一并交代清楚。
6.1 给正在使用的分区扩容时最容易犯的错
扩容是个高频需求,但不同文件系统的操作方式截然不同,而且很多不能“缩回去”。
ext4扩容的常规流程是:先用工具调整分区大小,然后执行resize2fs让文件系统扩展到新大小。xfs则是调整分区之后执行xfs_growfs。注意xfs不支持缩容,“想缩小一个xfs分区”这个需求基本上是无解的,只能备份重来。这个差异在你当初选文件系统时就应该心里有数,别等装满了才临时抱佛脚。
还有一个更隐蔽的坑:很多人以为调整完分区大小后文件系统会自动变大,实际上内核识别到的分区表信息和文件系统元数据不一定同步更新。所以你扩容后一定要执行resize相关的命令,不要只改分区表就以为完事了。操作顺序错了或者漏了,就会出现“分区显示变大了,可用空间却不变”的诡异现象。
6.2 卸载时target is busy的处理
要卸载一个分区,用:
umount /data可你经常会碰到系统回一句target is busy,意思是还有进程在使用这个挂载点下的文件。这时候别急着强拆,先用lsof /data或者fuser -mv /data看看是哪个进程占着。最常见的是你的shell当前工作目录就在里面,cd出来就没事;也有可能是某个服务还在后台读写。
找到罪魁祸首之后,要么结束对应进程,要么用lazy unmount:
umount -l /data这种懒卸载让系统先断开挂载关系,等所有进程不再使用时自动清理,比强制卸载温和一点。但要注意,它仍然有风险,如果此时有进程正在写数据,可能会丢数据。所以生产环境里的卸载操作,我建议宁可多花时间确认进程,也不要赌那一个 -l 参数。
6.3 数据盘换新机器的迁移思路
换机器、换机房、换云平台的时候,数据盘的迁移是个硬活。最安全的思路永远是先文件级备份,比如用rsync把/data的内容同步到新机器的对应目录,校验无误后再切换服务。直接拔盘插新机器在纯物理环境也许能跑,但涉及虚拟化平台、驱动差异、分区表类型兼容性的时候,踩坑率陡增。
如果非要拔盘迁移,操作前至少要做这些事:记录分区表结构,检查文件系统完整性,确认新机器内核支持该文件系统类型,并提前准备好内核模块。迁移完成后第一时间检查挂载点权限和所有者,这个细节很多人漏掉,结果数据都在,程序却因为权限不对起不来。权限文件在文件系统里同样有元数据,拔盘迁移之后经常出现user ID对不上的情况。
我个人在实际操作中的最大体会是:整套分区挂载流程,真正的门槛不在命令,而在于操作前有没有建立“确认目标设备、确认分区表、确认数据可丢”的三确认习惯。你在/dev/sdb1上敲一条 mkfs,敲之前多花三十秒看一眼lsblk,比什么高级技巧都管用。后面如果继续写这个系列,我可能会接着展开LVM逻辑卷管理、swap分区、以及系统盘和数据盘分离的最佳实践。这一篇你先把从零到一跑通,后面的东西自然就顺了。