Linux磁盘与文件系统

Linux中每个装置都被当成一个文件,硬盘文件名为/dev/sd[a-p],若使用的是云机,可能得到的是虚拟机,虚拟机内的磁盘是使用仿真器生成的磁盘文件名为/dev/vd[a-p],软件磁盘阵列通常为/dev/md[0-128]的格式,LVM的磁盘通常为/dev/VGNAME/LVNAME

装置 Linux内的文件名
SCSI/SATA/USB硬盘机 /dev/sd[a-p]
USB快闪碟 /dev/sd[a-p](与SATA相同)
Virt I/O界面 /dev/vd[a-p](用于虚拟机内)
软盘驱动器 /dev/fd[0-7]
打印机 /dev/input/mouse[0-15](通用)
/dev/psaux(PS/2界面)
/dev/mouse当前鼠标
CDROM/DVDROM /dev/scd[0-1](通用)
/dev/sr[0-1](通用)
/dev/cdrom当前CDROM
磁带机 /dev/ht0(IDE界面)
/dev/st0(SATA/SCSI界面)
/dev/tape当前磁带
IDE硬盘机 /dev/hd[a-d](旧系统才有),会被仿真成/dev/sd[a-p]

SATA/USB/SAS等磁盘接口都是使用SCSI模块来驱动的,故这些接口的磁盘装置文件名都是/dev/sd[a-p]的格式,SATA/USB接口的磁盘是没有顺序的,其装置文件名是根据Linux核心侦测到的。如一个PC主板上有六个SATA插槽,两个SATA分别位于SATA1和SATA5,以及一个USB,此时SATA1上的装置文件名为/dev/sda,SATA2上的装置文件名为/dev/sdb,USB磁盘在开机完成后才会被系统捕捉到装置名为/dev/sdc

MSDOS与GPT

磁盘的组成磁盘盘机械手臂磁盘读取头主轴马达,数据写入是在磁盘盘面上,磁盘盘面又分为扇区磁道,所有磁盘的同一个磁道称为磁柱Cylinder扇区是最小的物理存储单位,其的物理设计大小有512bytes4Kbytes两种。

整个磁盘的第一扇区特别重要,其记录了整个磁盘的重要信息,早期磁盘第一个扇区中含有重要信息故被称为MBRMaster Boot Record格式主要开机记录区也叫MSDOS由于磁盘容量不断扩大从而产生了新的磁盘分区格式GPTGUID partition table,其分区数量扩充较多,磁盘容量也可以超过2TB

由于每种操作系统所设定的文件属性/权限并不相同,为了存放这些文件所需的数据,磁盘分区完毕后还需要进行格式化之后操作系统才能够使用这个文件系统;windows 98以前的微软操作系统主要使用FATFAT16文件系统,windows 2000以后的版本有所谓的NTFS文件系统,Linux的正统文件系统则为Ext2Linux second extended file systemext2fs

传统磁盘与文件系统一个分区槽就是只能够被格式化成为一个文件系统,可以说一个文件系统就是一个分区槽;但LVM与软件磁盘阵列可将一个分区槽格式化为多个文件系统,也能将多个分区合并成一个文件系统,故称呼一个可被挂载的数据为一个文件系统而不是一个分区槽;

MBR

早期Linux为了兼容Windows磁盘,因此使用的是支持Windows的MBR主要开机记录区的方式来处理开机管理程序分区表,而MBR主要开机记录区分区表都放在磁盘的第一个扇区,该扇区通常是512bytes旧磁盘扇区都是512bytes

  • MBR主要开机记录区,Master Boot Record446bytes,可安装开机管理程序
  • partition table分区表64bytes,记录整个硬盘分区的状态

由于分区表所在区块只有64bytes容量,最多仅能存储四组记录区,每组记录区记录了该区段的起始结束磁柱号码,且四组记录区被称为Primary主要分区槽Extended延伸分区槽

  • 所谓分区只是针对该64bytes分区表进行的设定
  • 磁盘默认的分区表仅能写入四组分区信息
  • 分区槽最小单位通常为磁柱
  • 当系统要写入磁盘时,一定会参考磁盘分区表,才能针对某个分区槽进行数据的处理

之所以要分区是出于安全考虑,当对某个分区槽的数据重整时,不会影响到其他分区槽的数据,是数据更安全,系统效能考虑,当读取数据时,只会读取某个分区槽的指定磁柱范围,有助于数据读取速度与效能。

最多仅能存储四组记录区,并不代表最多只能分区出四个分区槽,可利用延伸分区来记录更多的分区信息,从而来将磁盘分出更多分区,实际上延伸分区并不是只占一个分区,而是会分布在每个分区槽的最前面几个扇区来记载分区信息。延伸分区的目的是使用额外的扇区来记录分区信息,延伸分区本身并不能被拿来格式化,可以通过延伸分区所指向的那个区块继续做分区的记录。由延伸分区继续分区出来的分区槽被称为逻辑分区槽,且逻辑分区槽的装置名称号码由5开始

分区以磁柱为单位连续磁盘空间,且延伸分区又类似独立的磁盘空间,若延伸分区被破坏所有逻辑分区将会被删除,这是因为逻辑分区的信息都记录在延伸分区中,MBR主要分区、延伸分区与逻辑分区的特性:

  • 由于MBR硬盘的限制主要分区延伸分区加起来最多只能有4
  • 由于操作系统限制,延伸分区最多只能有一个
  • 逻辑分区是由延伸分区持续切割出来的分区槽
  • 延伸分区无法格式化,作为数据存取的主要分区逻辑分区才能被格式化
  • 逻辑分区的数量依操作系统而不同,Linux中SATA硬盘已经可以突破63个以上的分区限制

由于第一个扇区所记录的分区表MBR特别重要,几乎只要读取硬盘都会先由这个扇区先读起,若硬盘第一个扇区物理实体损坏,由于系统找不到分区表,不知道如何读取磁柱区间 ,则整个硬盘就损坏了。

若将系统分成四个主要分区,即使硬盘还有剩余空间也无法再继续分区,故若分区超过四个一定要有延伸分区,必须将所有剩余空间都分配给延伸分区,然后再以逻辑分区来规划延伸空间,考虑到磁盘的连续性,一般建议将延伸分区的磁柱号码分配在最后面的磁柱内

MBR分区表除了主分区、延伸分区、逻辑分区需要注意之外,由于每组分区表仅有16bytes,记录的信息相当有限,在过去MBR分区表的限制中经常可以发现如下的问题:

  • 操作系统无法抓取到2.2T以上的磁盘容量
  • MBR仅有一个区块,若被破坏后,经常无法或很难救援
  • MBR内存放开机管理程序的区块仅446bytes无法容纳较多的程序代码
GPT

过去一个扇区大小是512bytes,目前已有4K扇区,为了兼容于所有磁盘,在扇区定义中大多会使用Logical Block Address逻辑区块地址LBA来处理,GPT将磁盘所有区块以预设为512bytesLBA来规划,第一个LBA称为LBA0

相比于MBR仅使用第一个512bytes区块来记录分区信息不同,GPT使用了34LBA区块来记录分区信息,GPT整个磁盘的最后33LBA也拿来作为另一个备份

LBA0与MBR模式相似,该兼容区块也分为两个部份,一个是跟之前446bytes相似的区块,储存了第一阶段的开机管理程序,而在原本的分区表的纪录区内,该兼容模式仅放入一个特殊标志的分区,用来表示此磁盘为GPT格式,而不懂GPT分区表的磁盘管理程序,则不会识别这颗磁盘,除非用户有特别要求要处理该磁盘,否则该管理软件不能修改此分区信息,进一步保护了此磁盘。

LBA1为GPT表头纪录,记录了分区表本身的位置与大小,同时记录了备份用的GPT分区即在最后34个LBA区块放置的位置, 同时放置了分区表检验机制码CRC32操作系统可根据该检验码来判断GPT是否正确,若有错误还可透过该记录区来取得备份的GPT即磁盘最后的备份区块来恢复GPT的正常运作。

LBA2-33实际记录分区信息处,从LBA2区块开始每个LBA都可纪录4分区纪录,默认总共可有4*32 = 128个分区记录,因为每个LBA有512bytes,因此每个记录用到128bytes的空间,除了每笔记录所需要的标识符与相关的纪录之外,GPT在每笔纪录中分别提供64bits来记载开始和结束扇区号码,因此GPT分区表对于单一分区槽来说, 其最大容量限制264 * 512bytes = 263 * 1Kbytes = 233*TB = 8 ZB,注意1ZB = 230TB

现在GPT分区预设可以提供多达128笔纪录,Linux本身核心装置纪录中,针对单一磁盘来说,虽然过去最多只能到达15个分区槽,但由于Linux kernel透过udev等方式的处理,现在Linux已经没有该限制了,且GPT分区没有主、延伸、逻辑分区的概念,每笔纪录都可独立存在,每个都可视为主分区,每一个分区都可拿来格式化使用。

BIOS与UEFI

目前的主机系统在加载硬件驱动方面的程序,主要有早期的BIOS与新的UEFI两种机制,CMOS是记录各项硬件参数嵌入在主板上面的储存器,BIOS则是一个写入到主板上的一个软件程序,即开机时计算机系统会主动执行的第一个程序。

以硬盘为例,BIOS会依据使用者的设定去获取能开机的硬盘,且到该硬盘中读取第一个扇区的MBR位置MBR中仅有446 bytes的硬盘容量里面会放置最基本的开机管理程序, 此时BIOS就功成圆满,接下来就是MBR内的开机管理程序的工作了,开机管理程序的目的是在加载核心文件

整个开机流程到操作系统之前的动作,若分区表为GPT格式,则BIOS也能够从LBA0的MBR兼容区块读取第一阶段的开机管理程序代码:

  • BIOS:开机主动执行的程序,会识别第一个可开机的装置
  • MBR:第一个可开机装置的第一个扇区内的主要启动记录区块,内含开机管理程序
  • boot loader开机管理程序:一支可读取核心文件来执行的软件
    • 提供选单:用户可选择不同的开机项目,即多重引导的重要功能
    • 载入核心文件:直接指向可开机的程序区段来开始操作系统
    • 转交其他loader:将开机管理功能转交给其他loader负责,可能具有多个开机管理程序
  • 核心文件:开始操作系统的功能

文件系统

Linux文件系统通常会将权限与属性放置到inode,且一个文件占用一个inode同时记录此文件的数据所在的block号码实际数据则放置到data block区块中若文件比较大会占用多个block;还有一个超级区块 superblock会记录整个文件系统的整体信息包括inodeblock总量使用量剩余量以及文件系统的格式与相关信息;每个inodeblock都有编号,这种文件系统称为索引式文件系统基本上不需要进行碎片整理

除此之外还有FAT格式的文件系统,FAT文件系统没有inode,每个block号码都记录在前一个block,只能一个一个的读取,若同一个文件数据写入block太过分散,磁头无法再磁盘转一圈就读取到所有数据,通常碎片整理的原因就是文件写入的block太过离散文件读取很差,此时可通过碎片整理将同一个文件所属的blocks汇整在一起,FAT文件系统需要经常的碎片整理一下;

标准Linux文件系统Ext2就是使用inode为基础的文件系统,且文件系统一开始就将inode与block规划好了,除非重新格式化或利用resize2fs等指令变更文件系统大小,否则inode与block固定后就不再变动;Ext2文件系统在格式化时基本上是区分为多个区块群组,每个区块群组都有独立的inode/block/superblock系统;整体的规划当中文件系统最前面有一个启动扇区boot sector,该启动扇区可安装开机管理程序;

Ext2文件系统中所支持的block大小有1K2K4K三种;在格式化时block的大小就固定了且每个block都有编号,以便inode的记录;block大小的差异会导致该文件系统能够支持的最大磁盘容量最大单一文件容量不相同;每个block内最多只能够放置一个文件的数据;若文件大于block则一个文件会占用多个block,若小于block则该block的剩余容量就不能够再被使用了,会造成磁盘空间会浪费

inode记录的文件权限rwx、拥有者、组、容量、创建或状态改变时间ctime、最近一次读取时间atime、最近修改时间mtimeSUIDSGIDSBIT、该文件block编号;且每个Inode大小固定为128bytes,新的ext4xfs可设定到256 bytes;每个文件都仅占用一个inode;文件系统能够建立的文件数量与inode的数量有关;系统读取文件时需先找到inode并分析inode所记录的权限与用户是否符合,若符合才能够开始实际读取block的内容;

inode记录一个block号码要4byte,inode记录block号码的区域定义为12个直接一个间接一个双间接一个三间接记录区;12个直接即直接存储12block编号;所谓的间接就是再拿一个block来记录block号码;双间接即第一个block仅再指出下一个记录编号的block;实际记录的在第二个block;三间接就是利用第三层block来记录编号

1K的block为例,能够容纳的最大文件为16GB = 12 + 256 + 65536 + 16777216,该方法不能用在2K4K的block大小的计算, 因为大于2Kblock将会受到Ext2文件系统本身的限制计算结果会不太符合:

  • 12个直接12 X 1K = 12K
  • 间接:每个block编号4byte,一个1K的block可存储256个block编号,故256 X 1K = 256K
  • 双间接256 X 256 X 1K = 65536K
  • 三间接256 X 256 X 256 X 1K = 16777216K
superblock

Superblock是记录整个filesystem相关信息的地方,大小为1024bytes,主要记录blockinode数量使用未使用inodeblock的数量;单个block和inode的大小,block1, 2, 4Kinode128bytes256bytes;filesystem的挂载时间最近一次写入数据的时间最近一次检验磁盘fsck的时间等;以及一个valid bit数值,若此文件系统已被挂载valid bit0未被挂载valid bit1

每个block group都可能含有superblock,但一个文件系统应该仅有一个superblock,事实上除了第一个block group内会含有superblock之外,后续block group不一定含有superblock若含有则该superblock主要是做为第一个block group内superblock的备份

Filesystem Description

该区段可描述每个block group的开始与结束的block号码,以及说明每个区段superblock,bitmap,inodemap,data block分别介于哪一个block号码之间;

block bitmap & inode bitmap

block bitmap用于记录使用与未使用的block;inode bitmap用于记录使用与未使用的inode;

常用指令

可以使用dumpe2fs指令查询Ext家族superblock信息,blkid指令可列出系统有被格式化的设备

1
2
3
4
dumpe2fs [-bh] 装置文件名
选项与参数:
-b :列出保留为坏轨的部分,一般用不到
-h :仅列出superblock的数据,不会列出其他的区段内容

Linux文件系统创建目录时文件系统会分配一个inode与至少一块block给该目录,其中inode记录该目录的相关权限与属性,并可记录分配到的block号码;而block则记录该目录下的文件名与该文件名占用的inode数据;可通过ls -i选项来查看文件所对应的inode号码;当使用ls -l时出现的目录几乎都是1024的倍数,因为每个block的容量都是1K, 2K, 4K目录并不只会占用一个block,若目录中文件数太多而导致一个block无法容纳下所有的文件名和其对应的inode对照表时,Linux会给予该目录多个block;

1
2
3
4
5
6
ll -d / /boot /usr/sbin /proc /sys
drwxr-xr-x. 18 root root 4096 12月 10 19:28 / # 1 个 4K block
dr-xr-xr-x. 5 root root 4096 2月 16 2022 /boot # 1 个 4K block
dr-xr-xr-x 203 root root 0 12月 11 03:27 /proc # 为内存内数据,不占磁盘容量
dr-xr-xr-x 13 root root 0 12月 11 03:27 /sys # 为内存内数据,不占磁盘容量
dr-xr-xr-x. 2 root root 20480 2月 18 2022 /usr/sbin # 5 个 4K block

Linux下的ext2文件系统中创建一个一般文件时, ext2文件系统会分配一个inode与相对于该文件大小的block数量给该文件,如假设一个 block为4 Kbytes,而要建立一个100 KBytes的文件,则linux将分配一个inode与25 个 block来储存该文件,注意由于inode仅有12个直接指向,因此还要多一个block来作为区块号码的记录;

inode本身并不记录文件名文件名是记录在目录的block,因此新增/删除/修改文件名目录的w权限有关,读取某个文件时务必会经过目录的inode与block,然后才能够找到待读取文件的inode号码,最终才会读到该文件的block内的数据;

新建一个文件时,文件系统会先确定用户对于欲新增文件的目录是否具有w与x的权限,若有才能新增;根据inode bitmap找到未被使用的inode,并将新文件的权限/属性写入;根据block bitmap找到未被使用的block,并将实际的数据写入block中,且更新inode的block指向数据;将刚刚写入的inode与block数据同步更新inode bitmap与block bitmap,并更新superblock内容;

早期Ext2文件系统中,若发生数据不一致问题,系统在重启时会通过superblock中记录的valid bit与filesystem state等状态来判断是否强制进行数据一致性检查,需要检查时通过e2fsck程序来完成;若文件系统有100G以上且文件非常多时,检查会非常耗时;为了避免该问题文件系统中专门规划出一个区块,用于记录写入或修改文件时的步骤:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息,然后写入文件的权限与数据,更新superblock、block bitmap、inode bitmap的数据,在日志记录区块当中完成该文件的纪录;万一发生不一致问题系统只需检查日志记录区块,而不必针对整块filesystem去检查;

所有的数据都要加载到内存后CPU才能对该数据进行处理,若编辑一个很大的文件在编辑过程中又频繁的要系统来写入到磁盘中,由于磁盘写入速度比内存慢很多,因此会等待磁盘写入/读取,为了解决该效率问题,Linux使用异步处理的方式;当系统加载一个文件到内存,若该文件未被修改,则在内存区段的文件数据会被设定为干净的,若内存中的文件数据被修改过,此时该内存中的数据会被设定为脏的,此时所有的动作都还在内存中执行,并没有写入到磁盘中,系统会不定时的将内存中设定为脏的数据写回磁盘,以保持磁盘与内存数据的一致性,也可利用sync指令来手动强迫写入磁盘;若正常关机时关机指令会主动调用sync来将内存的数据回写入磁盘内;

文件系统目录树结合的动作称为挂载挂载点一定是目录,该目录为进入该文件系统的入口,CentOS 7.x应该会有/, /boot, /home三个挂载点,如下可以发现/, /boot, /home三个不同的filesystem,因为每一行的文件属性并不相同,且三个目录的挂载点也均不相同:

1
2
3
4
ls -lid / /boot /home
64 drwxr-xr-x. 18 root root 4096 12月 10 19:28 /
64 dr-xr-xr-x. 5 root root 4096 2月 16 2022 /boot
64 drwxr-xr-x. 5 root root 50 7月 31 2022 /home

同一个filesystem的某个inode只会对应到一个文件内容,可通过判断inode来确认不同文件名是否为相同的文件,由于挂载点均为/,因此三个文件/, /., /..均在同一个filesystem内,而这三个文件的inode号码均为64,因此这三个文件都指向同一个inode,故这三个文件的内容也就完全一样:

1
2
3
4
ls -ild / /. /..
64 drwxr-xr-x. 18 root root 4096 12月 10 19:28 /
64 drwxr-xr-x. 18 root root 4096 12月 10 19:28 /.
64 drwxr-xr-x. 18 root root 4096 12月 10 19:28 /..

Linux标准文件系统是ext2,且还有增加了日志功能的ext3ext4,Linux还支持很多文件系统格式,尤其是最近几年推出了好几种速度很快的日志式文件系统,包括SGIXFS文件系统,可适用更小型文件的Reiserfs文件系统,以及Windows的FAT文件系统等,Linux常见的支持文件系统有:

  • 传统文件系统ext2minixMS-DOSFAT (用vfat模块) 、iso9660 (光盘)等等;
  • 日志式文件系统ext3ext4ReiserFSWindows' NTFSIBM's JFSSGI's XFSZFS
  • 网络文件系统NFSSMBFS
1
2
3
4
5
# 查看支持的文件系统有哪些
ls -l /lib/modules/$(uname -r)/kernel/fs

# 系统目前已加载到内存中支持的文件系统
cat /proc/filesystems

整个Linux系统都是通过Virtual Filesystem SwitchVFS的核心功能去读取filesystem的,使用者并不需要知道每个partition的filesystem是什么,都是通过VFS的功能来管理所有的filesystem;

XFS

CentOS 7开始预设文件系统已经由EXT4变成了XFS文件系统,Ext文件系统采用的是预先规划出所有inode/block/metadata等数据,未来系统可直接取用不需要再进行动态配置,面对磁盘容量越来越大,系统预先分配inode和block的时间以及格式化的时间会越来越长;由于虚拟化的应用越来越广泛,而作为虚拟化磁盘来源的巨型文也就越来越常见,因此从CentOS 7.x开始文件系统已经由预设的Ext4变成了较适合高容量磁盘巨型文件效率较佳的文件系统xfs

xfs是一个日志式文件系统,几乎所有Ext4文件系统有的功能xfs都可以具备,xfs文件系统主要规划为三个部份:

  • 数据区data section:包括inode/data block/superblock等数据,分为多个储存区群组allocation groups来分别放置文件系统所需要的数据,且inode与block系统用到时才动态配置产生,所以格式化速度快,block容量可由512bytes ~ 64K调配,但Linux由于内存控制关系最高可使用的block大小为4K,超过4K就挂载不了,inode容量可由256bytes~2M,每个allocation groups储存区群组都包含了以下几项:
    • 整个文件系统的superblock
    • 剩余空间的管理机制
    • inode的分配追踪
  • 文件系统活动登录区log section:主要被用来记录文件系统的变化,有点像是日志区,文件的变化会在这里记录下来,直到该变化完整的写入到数据区后,该笔纪录才会被终结,若出现数据一致性问题系统会拿该区块来进行检验,藉以快速的修复文件系统;该区域可以指定外部的磁盘SSD
  • 实时运行区realtime section:当创建文件时xfs会在该区段找1~Nextent区块,将文件放置在该区块内,等到分配完毕后,再写入到data section的inode与block,该extent区块的大小需在格式化时就指定,最小值4K最大1G

可使用xfs_info命令查询XFS文件系统的superblock内容,类似于EXT文件系统中的dumpe2fs命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
xfs_info 挂载点|装置文件名

# 找出系统/boot挂载点下的文件系统的superblock记录
df -T /boot
文件系统 类型 1K-块 已用 可用 已用% 挂载点
/dev/sda2 xfs 972452 222216 750236 23% /boot

xfs_info /dev/sda2
meta-data=/dev/sda2 isize=512 agcount=4, agsize=60992 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0 spinodes=0
data = bsize=4096 blocks=243968, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal bsize=4096 blocks=855, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

isizeinode的容量512bytesagcount储存区群组allocation group的个数agsize指每个储存区群组具有60992blockbsizeblock的容量4Kblocks为该文件系统block总数,整个文件系统的容量4 * 60992 * 4Ksectsz逻辑扇区sector的容量internal指文件系统活动登录区是在文件系统内不是在外部设备中,且占用4K * 855个block;realtime表示实时运行区extent容量为4K

磁盘与目录容量

磁盘的整体数据是在superblock区块中,但每个文件各自的容量则在inode当中记载的,可通过下面两个命令查询:

  • df:列出文件系统的整体磁盘使用量df主要读取数据几乎都是针对整个文件系统,因此读取的主要是在Superblock内的信息,所以该指令显示结果速度非常快
  • du:评估文件系统的磁盘使用量,常用在推估目录所占容量,直接到文件系统内去搜寻所有的文件数据,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 不加任何选项默认会将系统内所有不含特殊内存内的文件系统与swap,都以1 Kbytes的容量来列出来
df [-ahikHTm] [目录或文件名]
选项与参数:
-a :列出所有的文件系统,包括系统特有的/proc等文件系统;
-k :以 KBytes 的容量显示各文件系统;
-m :以 MBytes 的容量显示各文件系统;
-h :以人们较易阅读的 GBytes, MBytes, KBytes 等格式自行显示;
-H :以 M=1000K 取代 M=1024K 的进位方式;
-T :连同该 partition 的 filesystem 名称 (例如 xfs) 也列出;
-i :不用磁盘容量,而以inode的数量来显示

# 将/etc底下的可用磁盘容量以易读的容量格式显示
df -h /etc

# 不加任何选项默认会分析当前所在目录的文件与目录所占用的磁盘空间,实际显示时仅显示目录容量不显示文件,单位是K
du [-ahskm] 文件或目录名称
选项与参数:
-a :列出所有的文件与目录容量,因为默认仅统计目录底下的文件量而已。
-h :以人们较易读的容量格式 (G/M) 显示;
-s :列出总量而已,而不列出每个目录占用容量;
-S :不包括子目录下的总计,与 -s 有点差别。
-k :以 KBytes 列出容量显示;
-m :以 MBytes 列出容量显示;

# 检查根目录底下每个目录所占用的容量
du -sm /*

链接

每个文件都会占用一个inode,想要读取该文件必须要经过目录记录的文件名来指向到正确的inode号码才能读取,硬链接只是在某目录下新增一笔文件名链接到某inode号码的关联记录而已,既不会增加inode也不会消耗block数量,若新增的记录刚好将目录的block填满,还是会新增一个block;

通过1或2的目录的inode指定的block找到两个不同的文件名,不管使用哪一个文件名均可指向real的inode去读取最终的数据,最大的好处是安全,若将任何一个文件名删除,inode和block都还存在;硬链接只能在单一文件系统中使用,不能跨文件系统,不能硬链接目录;若将/etc使用硬链接建立一个/etc_hd的目录时,则在/etc_hd下的所有文件同时都与/etc下的文件要建立hard link,而不仅链接到/etc_hd与/etc而已,且未来若需要在/etc_hd下创建新文件时,连带/etc下又得建立一次hard link,因此会造成环境相当大的复杂度;

软链接Symbolic link是建立一个独立的文件,而该文件会让数据的读取指向其link文件的inode,与windows的快捷方式类似,会占用inodeblock,由于只是利用文件来做为指向的动作,当源文件删除后symbolic link的文件会打不开

1
2
3
4
ln [-sf] 来源文件 目标文件
选项与参数:
-s :若不加任何参数即创建hard link,-s即symbolic link
-f :若目标文件存在时,就主动的将目标文件直接移除后再创建

关于目录的link数量,当新建目录时目录的link数为2,而其上一层目录link数据会增加1;因为存在...两个目录;

磁盘分区&格式化&校验&挂载

对磁盘分区建立可用的partition,partition进行格式化以建立可用的filesystem,并对建立的filesystem进行检验,Linux上需建立挂载点即目录,将filesystem挂载到挂载点上;目前磁盘分区主要有MBR以及GPT两种格式,可分别使用fdiskgdisk命令来处理分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
lsblk [-dfimpt] [device]
选项与参数:
-d :仅列出磁盘本身,并不会列出该磁盘的分区数据
-f :同时列出该磁盘内的文件系统名称
-i :使用 ASCII 的线段输出,不要使用复杂的编码 (再某些环境下很有用)
-m :同时输出该装置在 /dev 底下的权限数据 (rwx 的数据)
-p :列出该装置的完整文件名!而不是仅列出最后的名字而已。
-t :列出该磁盘装置的详细数据,包括磁盘队列机制、预读写的数据量大小等

# 列出本系统下的所有磁盘与磁盘内的分区信息
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 232.9G 0 disk
├─sda1 8:1 0 476M 0 part /boot/efi
├─sda2 8:2 0 953M 0 part /boot
├─sda3 8:3 0 141G 0 part /home
├─sda4 8:4 0 74.5G 0 part /
└─sda5 8:5 0 5.6G 0 part

# 仅列出 /dev/vda 装置内的所有数据的完整文件名
lsblk -ip /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
/dev/sda 8:0 0 232.9G 0 disk
|-/dev/sda1 8:1 0 476M 0 part /boot/efi
|-/dev/sda2 8:2 0 953M 0 part /boot
|-/dev/sda3 8:3 0 141G 0 part /home
|-/dev/sda4 8:4 0 74.5G 0 part /
`-/dev/sda5 8:5 0 5.6G 0 part
  • NAME:设备名,会省略/dev等前导目录
  • MAJ:MIN:设备主要代码,设备次要代码
  • RM:是否为可卸除装置 (removable device),如光盘、USB 磁盘等等
  • SIZE:设备容量
  • RO:是否为只读设备
  • TYPE:是磁盘 (disk)、分区槽 (partition) 还是只读存储器 (rom) 等输出
  • MOUTPOINT:挂载点

可使用lsblk列出本系统下的所有磁盘与磁盘内的分区信息,可通过-f参数来列出文件系统设备UUID数据,也可以使用blkid命令来找出设备的UUID,UUID是全局唯一标识符,Linux会将系统内所有设备都给予一个独一无二的标识符,该标识符可拿来作为挂载或使用该设备或文件系统之用;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 列出本系统下的所有磁盘与磁盘内的分区信息
lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda1 vfat B99A-7DF9 /boot/efi
├─sda2 xfs f0dda9b9-4595-4c0a-b084-b7c87808f83c /boot
├─sda3 xfs 673e388b-5ac9-42e0-a29d-c76bd6b0bf22 /home
├─sda4 xfs fcb72d23-6dc8-40db-9065-590c3f8d2dbe /
└─sda5 swap 9dc5c38e-fbd4-48dc-ab2b-15f772fbe19f

blkid
/dev/sda6: UUID="f0203a66-3bce-4d79-a40e-6f3a2396dcd5" TYPE="ext4" PARTLABEL="Linux filesystem" PARTUUID="20077c57-aa6f-4bd7-8f38-e6396a77c7a9"
/dev/sda1: SEC_TYPE="msdos" UUID="B99A-7DF9" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="241fa0a3-b322-4ea1-96b0-71483861e8be"
/dev/sda2: UUID="f0dda9b9-4595-4c0a-b084-b7c87808f83c" TYPE="xfs" PARTUUID="6eb73d00-2b3d-4f32-9d40-b7a5ae2254ab"
/dev/sda3: UUID="673e388b-5ac9-42e0-a29d-c76bd6b0bf22" TYPE="xfs" PARTUUID="d5acb22f-2986-45bd-9a04-934c355cfce0"
/dev/sda4: UUID="fcb72d23-6dc8-40db-9065-590c3f8d2dbe" TYPE="xfs" PARTUUID="e3b63683-bef8-4a9a-b793-7a05d3dd8d0e"
/dev/sda5: UUID="9dc5c38e-fbd4-48dc-ab2b-15f772fbe19f" TYPE="swap" PARTUUID="8078106c-b330-45ad-aff5-cfb85dff23e7"

可通过parted命令列出磁盘的分区表类型分区信息,虽然可以使用gdisk和fdisk很快速的完成分区槽的分割,但gdisk主要针对GPT而fdisk主要支持MBR对GPT支持不够,使用不同的分区时,得要先查询到正确的分区表才能用适合的指令,非常麻烦,可以使用同时支持两种分区类型的命令parted

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
parted [装置] [指令 [参数]]
选项与参数:
新增分区:mkpart [primary|logical|extended] [ext4|vfat|xfs] 开始 结束
显示分区:print
删除分区:rm [partition]

# 列出/dev/sda磁盘的相关数据
parted /dev/sda print
Model: ATA Samsung SSD 750 (scsi)
Disk /dev/sda: 250GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number Start End Size File system Name 标志
1 1049kB 500MB 499MB fat16 EFI System Partition 启动
2 500MB 1499MB 999MB xfs
3 1499MB 153GB 151GB xfs
4 153GB 233GB 80.0GB xfs
5 233GB 239GB 6000MB linux-swap(v1)
6 239GB 240GB 1074MB ext4 Linux filesystem
7 240GB 241GB 537MB linux-swap(v1) Linux swap

# 固定使用MB作为单位显示
parted /dev/vda unit mb print
# 将/dev/sda这个原本的MBR分区表变成GPT分区表
parted /dev/sda mklabel gpt
# 建立一个约为512MB容量的分区槽
parted /dev/vda mkpart primary fat32 36.0GB 36.5GB

# 删除编号为7的分区
parted /dev/vda rm 7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present

Found valid GPT with protective MBR; using GPT. # 找到了 GPT 的分区表

Command (? for help): ? # 可输入指令动作,可以按问号 (?) 来查看可用指令
b back up GPT data to a file
c change a partition's name
d delete a partition # 删除一个分区
i show detailed information on a partition
l list known partition types
n add a new partition # 增加一个分区
o create a new empty GUID partition table (GPT)
p print the partition table # 印出分区表 (常用)
q quit without saving changes # 不储存分区就直接离开 gdisk
r recovery and transformation options (experts only)
s sort partitions
t change a partition's type code
v verify disk
w write table to disk and exit # 储存分区操作后离开 gdisk
x extra functionality (experts only)
? print this menu

Command (? for help): p
Disk /dev/sda: 488397168 sectors, 232.9 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7B10AC68-EEE7-42BC-9088-3BB71109903A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 488397134
Partitions will be aligned on 2048-sector boundaries
Total free space is 21805357 sectors (10.4 GiB)

Number Start (sector) End (sector) Size Code Name
1 2048 976895 476.0 MiB EF00 EFI System Partition
2 976896 2928639 953.0 MiB 0700
3 2928640 298627071 141.0 GiB 0700
4 298627072 454875135 74.5 GiB 0700
5 454875136 466593791 5.6 GiB 8200

首先通过lsblkblkid找到磁盘,再用parted /dev/xxx print找出内部的分区表类型,之后才用gdiskfdisk操作系统,注意使用设备名请不要加上数字,因为partition是针对整个磁盘设备的而不是某个partition,故执行gdisk /dev/vda1会发生错误;

  • Number分区槽编号,1号指的是/dev/vda1
  • Start (sector):每一个分区槽的开始扇区号码位置
  • End (sector):每一个分区的结束扇区号码位置,与 start 之间可以算出分区槽的总容量
  • Size:就是分区槽的容量
  • Code:在分区槽内的可能的文件系统类型Linux8300swap8200
  • Name:文件系统的名称

当创建新的分区后,因为这颗磁盘目前正在使用当中,因此系统无法立即加载新的分区表,可通过重启partprobe命令来处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat /proc/partitions
major minor #blocks name

8 0 244198584 sda
8 1 487424 sda1
8 2 975872 sda2
8 3 147849216 sda3
8 4 78124032 sda4
8 5 5859328 sda5

partprobe -s
/dev/sda: gpt partitions 1 2 3 4 5 6

lsblk /dev/sda
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 232.9G 0 disk
├─sda1 8:1 0 476M 0 part /boot/efi
├─sda2 8:2 0 953M 0 part /boot
├─sda3 8:3 0 141G 0 part /home
├─sda4 8:4 0 74.5G 0 part /
├─sda5 8:5 0 5.6G 0 part
└─sda6 8:6 0 1G 0 part

fdiskgdisk使用的方式几乎一样,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
fdisk /dev/sda 
WARNING: fdisk GPT support is currently new, and therefore in an experimental phase. Use at your own discretion.
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

命令(输入 m 获取帮助):m
命令操作
d delete a partition # 删除一个 partition
g create a new empty GPT partition table
G create an IRIX (SGI) partition table
l list known partition types
m print this menu
n add a new partition # 新增一个 partition
o create a new empty DOS partition table
p print the partition table # 在屏幕上显示分区表
q quit without saving changes # 不储存离开 fdisk 程序
s create a new empty Sun disklabel
t change a partition's system id
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)

分区完成后需要对文件系统格式化,格式化命令为mkfs,应该称为构建文件系统make filesystem才对,agcount可根据CPU的核心数来设定,可通过grep 'processor' /proc/cpuinfo查询系统CPU核心数;RAID表示磁盘阵列分区区块stripe的数值大多介于4K1M之间,与文件数据容量以及性能相关性较高,若系统大多是大型文件时建议分区区块stripe设置大一些,磁盘阵列读/写频率会降低性能能会提升;若小文件比较多分区区块stripe建议设置为64K左右

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
mkfs.xfs [-b bsize] [-d parms] [-i parms] [-l parms] [-L label] [-f] [-r parms] 装置名称
选项与参数:
单位:只要谈到数值时,没有加单位则为bytes,可用k,m,g,t,p小写等来解释比较特殊的是s这个单位,它指的是sector的个数
-b :后面接的是block容量,可由512到64k,Linux最大容量限制为4k
-d :后面接的是data section的相关参数值,主要的值有:
agcount=数值 :设定需要几个储存群组的意思(AG),通常与CPU有关
agsize=数值 :每个AG设定为多少容量的意思,通常agcount/agsize只选一个设定即可
file :指的是格式化的装置是个文件而不是个设备(如虚拟磁盘)
size=数值 :data section的容量,即可不将全部的设备容量用完
su=数值 :当有磁盘阵列RAID时,分区区块stripe数值,与下面的sw搭配使用
sw=数值 :当有磁盘阵列RAID时,用于储存数据的磁盘数量(须扣除备份碟与备用碟)
sunit=数值 :与su相当,不过单位使用的是几个sector(512bytes大小)
swidth=数值 :就是su*sw的数值,但是以几个sector(512bytes大小)来设定
-f :如果设备内已经有文件系统,则需要使用这个-f 来强制格式化才行
-i :与inode有较相关的设定,主要的设定值有:
size=数值 :最小256bytes最大2k,一般保留256
internal=[0|1]:log装置是否为内建?预设为1内建,若要用外部装置
logdev=device :log装置为后面接的那个装置上头的意思,需设定internal=0才可
size=数值 :指定这块登录区的容量,通常最小512个block,大约2M以上才行
-L :后面接这个文件系统的标头名称Label name的意思
-r :指定realtime section的相关设定值,常见的有:
extsize=数值 :一般不须设定,但有RAID时,最好设定与swidth的数值相同,最小为4K最大为1G


blkid /dev/sda6
/dev/sda6: PARTLABEL="Linux filesystem" PARTUUID="20077c57-aa6f-4bd7-8f38-e6396a77c7a9"

mkfs.xfs /dev/sda6
Discarding blocks...Done.
meta-data=/dev/sda6 isize=512 agcount=4, agsize=65536 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=262144, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

blkid /dev/sda6
/dev/sda6: UUID="05052ace-d0b2-448b-9470-830545f4a581" TYPE="xfs" PARTLABEL="Linux filesystem" PARTUUID="20077c57-aa6f-4bd7-8f38-e6396a77c7a9"

mkfs.xfs -f -d agcount=8 /dev/sd6

磁盘阵列是由多个磁盘组成的一个大磁盘,不但可加快读写速度,还可在某个磁盘坏掉时保证文件系统可运行;磁盘阵列RAID是通过将文件先细分为数个小型分区区块stripe后,然后将众多分区区块stripes分别放到磁盘阵列里面的所有磁盘,所以一个文件是被同时写入到多个磁盘中去;为了保证文件安全性,会保留数个备份磁盘,以及可能会会保留一个以上的备用磁盘;

当CPU核心数为2时,agcount指定为2,若磁盘阵列RAID分区区块stripe指定为256K,则su设定为256k,若磁盘阵列有8颗,则有一个parity备份碟,因sw设置为7,则数据宽度swidth256K*71792K,可指定extsize1792k;若想要格式化ext4文件系统,可使用mkfs.ext4命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mkfs.ext4 [-b size] [-L label] 装置名称
选项与参数:
-b :设定 block 的大小,有 1K, 2K, 4K 的容量
-L :后面接这个装置的标头名称

# 将/dev/sda6格式化为ext4文件系统
mkfs.ext4 /dev/sda6
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: 完成
文件系统标签= # 显示 Label name
OS type: Linux
块大小=4096 (log=2) # 每一个 block 的大小
分块大小=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks # 跟 RAID 相关性较高
65536 inodes, 262144 blocks # 总计 inode/block 的数量
13107 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=268435456
8 block groups # 共有 8 个 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376

Allocating group tables: 完成
正在写入inode表: 完成
Creating journal (8192 blocks): 完成
Writing superblocks and filesystem accounting information: 完成

mkfs是个综合指令当使用mkfs -t xfs时,它会去找mkfs.xfs相关的参数,若想知道系统还支持哪种文件系统的格式化功能,直接按两下tab键

1
2
3
4
5
6
7
mkfs[tab][tab]
mkfs mkfs.btrfs mkfs.cramfs mkfs.ext2 mkfs.ext3 mkfs.ext4 mkfs.fat mkfs.minix mkfs.msdos mkfs.vfat mkfs.xfs

# 将/dev/sd6重新格式化为VFAT文件系统
mkfs -t vfat /dev/sd6
# 将/dev/sd6重新格式化为ext4文件系统
mkfs.ext4 /dev/sd6

xfs文件系统发生异常时可使用xfs_repair命令来检查文件系统,若是ext4文件系统建议使用fsck.ext4命令来检查,当为root用户时且文件系统有问题时才使用该命令,或怀疑刚刚格式化成功的磁盘有问题时;正常状态下使用时可能会造成对系统的损害;由于xfs_repairfsck.ext4命令扫描磁盘时可能会造成部分文件系统修正,所以执行这两个命令时被检查的分区不能挂载到系统上;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 xfs_repair [-fnd] 装置名称
选项与参数:
-f :后面的装置其实是个文件而不是实体装置
-n :单纯检查并不修改文件系统的任何数据
-d :通常用在单人维护模式底下,针对根目录/进行检查与修复的动作!很危险!不要随便使用


fsck.ext4 [-pf] [-b superblock] 装置名称
选项与参数:
-p :当文件系统在修复时,若有需要回复y的动作时,自动回复y来继续进行修复动作
-f :强制检查!若fsck没有发现任何unclean的标志,不会主动进一步检查,若要强制fsck进一步检查,则加上-f参数
-D :针对文件系统下的目录进行优化配置
-b :后面接superblock的位置!一般用不到,但若superblock因故损毁时,通过该参数即可利用文件系统内备份的superblock来尝试修复,一般superblock备份在:1K block放在8193, 2K block放在16384, 4K block放在32768


dumpe2fs -h /dev/sda6 | grep 'Blocks per group'
dumpe2fs 1.42.9 (28-Dec-2013)
Blocks per group: 32768

fsck.ext4 -b 32768 /dev/sda6
e2fsck 1.42.9 (28-Dec-2013)
/dev/sda6 was not cleanly unmounted, 强制检查.
第一步: 检查inode,块,和大小
第二步: 检查目录结构
第3步: 检查目录连接性
Pass 4: Checking reference counts
第5步: 检查簇概要信息

/dev/sda6: ***** 文件系统已修改 *****
/dev/sda6: 11/65536 files (0.0% non-contiguous), 12955/262144 blocks

文件系统挂载

挂载点是进入磁盘分区槽文件系统入口单一文件系统不应该被重复挂载在不同的挂载点即目录中,单一目录不应该重复挂载多个文件系统,作为挂载点的目录,理论上应该都是空目录,若不为空挂载文件系统后,原目录内的内容将暂时消失,卸载分区槽后恢复;使用mount命令来将文件系统挂载到Linux系统上;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mount -a
mount [-l]
mount [-t 文件系统] LABEL='' 挂载点
mount [-t 文件系统] UUID='' 挂载点 # 鸟哥近期建议用这种方式喔!
mount [-t 文件系统] 装置文件名 挂载点
选项与参数:
-a :按照配置文件/etc/fstab的数据将所有未挂载的磁盘都挂载上来
-l :单纯的输入mount会显示目前挂载的信息,加上-l可增列Label名称
-t :可加上文件系统种类来指定欲挂载的类型,常见类型有:xfs,ext3,ext4,reiserfs,vfat,iso9660,nfs,cifs,smbfs
-n :默认系统会将实际挂载实时写入/etc/mtab中,某些情况下为了避免问题会刻意不写入可使用-n
-o :后面可以接一些挂载时额外加上的参数,如账号、密码、读写权限等:
async, sync: 此文件系统是否使用同步写入或异步的内存机制,预设为async
atime,noatime: 是否修改文件读取时间atime,为了效能某些时候可用noatime
ro, rw: 挂载文件系统成为只读ro或可擦写rw
auto, noauto: 允许此filesystem被以mount -a自动挂载
dev, nodev: 是否允许此filesystem上建立设备文件,dev为允许
suid, nosuid: 是否允许此filesystem含有suid/sgid的文件格式
exec, noexec: 是否允许此filesystem上拥有可执行binary文件
user, nouser: 是否允许此filesystem让任何使用者执行mount,一般mount仅root可进行,指定user参数可让一般user也能够对此partition进行mount
defaults: 默认值为:rw, suid, dev, exec, auto, nouser, async
remount: 重新挂载,在系统出错或重新更新参数时,很有用

CentOS7不需要-t参数也能自动分析最恰当的文件系统来尝试挂载需要的设备,这也是blkid能正确显示文件系统的原因,Linux通过分析superblock搭配Linux的驱动程序去测试挂载,系统主要哦参考以下两个文件来进行挂载测试:

  • /etc/filesystems:系统指定的测试挂载文件系统类型的优先级
  • /proc/filesystems:Linux系统已经加载的文件系统类型

Linux支持的文件系统驱动程序都写在/lib/modules/$(uname -r)/kernel/fs/目录中;推荐使用UUID来识别文件系统;也可以利用mount --bind命令来将某个目录挂载到另外一个目录;可通过umount命令将已挂载的文件系统卸载,卸载后可使用dfmount查看是否还存在目录树中,可通过设备文件名或挂载点来卸载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 该命令需要使用root用户执行,否则没有任务内容
blkid /dev/sda6
/dev/sda6: UUID="4f61cba1-c396-424e-8e19-b52874858c10" TYPE="ext4" PARTLABEL="Linux filesystem" PARTUUID="20077c57-aa6f-4bd7-8f38-e6396a77c7a9"

mkdir -p /data1/ext4
mount UUID="4f61cba1-c396-424e-8e19-b52874858c10" /data1/ext4

df /data1/ext4/
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/sda6 999320 2564 927944 1% /data1/ext4

# 将/data1/ext4重新挂载,并加入参数为rw、auto、sync
mount -o remount,rw,auto,sync /data1/ext4
# 将/data1/ext4/目录暂时挂载到/data2/xfs/
mount --bind /data1/ext4/ /data2/xfs/
# 将挂载的目录卸载掉
umount /data2/xfs

# 两个文件inode相同
ls -lid /data1/ext4/ /data2/xfs/
203639013 drwxr-xr-x 2 root root 6 12月 26 22:19 /data1/ext4/
203639013 drwxr-xr-x 2 root root 6 12月 26 22:19 /data2/xfs/

# 将装置文件卸除
umount [-fn] 装置文件名或挂载点
选项与参数:
-f :强制卸除,可用在类似网络文件系统NFS无法读取到的情况下
-l :立刻卸除文件系统,比-f还强
-n :不更新/etc/mtab情况下卸除

# 若在当前目录下是否无法卸载的
umount /data1/ext4

系统挂载也有一些限制:

  • 根目录必须挂载,且先于其他mount print被挂载
  • 其他mount print必须为已创建的目录,可任意指定,但一定要遵守FHS
  • 所有mount print同一时间只能被挂载一次
  • 所有partition在同一时间只能挂载一次
  • 卸载必须先将工作目录移到mount point及其子目录之外

可通过修改/etc/fstabfilesystem table配置文件实现开机挂载,且就是执行mount命令进行挂载时将选项和参数写入的该文件;且/etc/fstab还加入dump备份指令和fsck文件系统校验命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat /etc/fstab 
#
# /etc/fstab
# Created by anaconda on Mon Jan 24 03:25:14 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
设备/UUID 挂载点 文件系统 文件系统参数 dump fsck
UUID=fcb72d23-6dc8-40db-9065-590c3f8d2dbe / xfs defaults 0 0
UUID=f0dda9b9-4595-4c0a-b084-b7c87808f83c /boot xfs defaults 0 0
UUID=B99A-7DF9 /boot/efi vfat umask=0077,shortname=winnt 0 0
UUID=673e388b-5ac9-42e0-a29d-c76bd6b0bf22 /home xfs defaults 0 0
UUID=9dc5c38e-fbd4-48dc-ab2b-15f772fbe19f swap swap defaults 0 0

若将/dev/vda4每次开机都自动挂载/data/xfs,在/etc/fstab中追加如下数据,若通过mount临时挂载,每次重启后需要重新挂载:

1
UUID="e0fa7252-b374-4a06-987a-3cb14f415488" /data/xfs xfs defaults 0 0

/etc/fstab开机时的配置文件,但filesystem的挂载实际是记录到/etc/mtab/proc/mounts中的,每次修改filesystem的挂载时会同时更新这两个文件,但万一/etc/fstab输入的数据错误导致无法开机成功,在单人维护模式中由于文件状态为ready only无法修改/etc/fstab也无法更新/etc/mtab,此时可利用mount -n -o remount,rw /命令重新挂载;使用光盘镜像文件文件作为磁盘的方式时,不需要刻录但需要loop装置来将其挂载起来:

1
2
mkdir /data/centos_dvd
mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /data/centos_dvd

也可以制作一个大文件,然后将该文件格式化后挂载,通过这种方式还能够帮助我们解决很多系统的分区不合理的情况,可通过dd命令来创建空的文件,在Linux上使用xen软件,再配合loop device的文件类型来进行根目录的挂载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 建立一个512M大小的空文件在/srv/loopdev
# if是input file输入文件/dev/zero会一直输出0的装置
# of是output file将一堆零写入到后面接的文件中
# bs是每个block大小,就像文件系统那样的block 意义
# count则是总共几个bs的意思。所以bs*count就是这个文件的容量
dd if=/dev/zero of=/srv/loopdev bs=1M count=512
# 大型文件的格式化
mkfs.xfs -f /srv/loopdev
blkid /srv/loopdev
/srv/loopdev: UUID="4364721c-d693-458f-964d-fb0799a1972e" TYPE="xfs"
# 通过mount命令挂载
mount -o loop UUID="4364721c-d693-458f-964d-fb0799a1972e" /mnt

df /mnt
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/loop0 520868 26436 494432 6% /mnt


# 在/etc/fstab文件中添加如下内容
/srv/loopdev /data/file xfs defaults,loop 0 0

mkdir /data/file
mount -a
df /data/file

swap

早期在安装Linux时一定需要的两个partition一个是根目录,另外一个就是swap内存置换空间,若硬件的配备资源足够swap不会被系统所使用,物理内存不足时才会使用swap;CPU所读取的数据都来自于内存,当内存不足时为了让后续程序正常运行,因此在内存中暂不使用的程序数据会被挪到swap中,此时内存就会空出来给需要执行的程序加载;由于swap是用磁盘来暂时放置内存中的信息,故用到swap时主机磁盘灯会开始闪个不停;

个人用可以不设定swap,但若支持电源管理模式即Linux主机系统可以进入休眠模式的话,运行中的程序状态会被纪录到swap中作为唤醒主机的状态依据,若是服务器的话由于不知道何时会有大量网络请求最好预留swap来缓冲系统内存用量;若系统已经建立完成,但发现没有创建swap分区,可先设定一个swap分区,在创建一个虚拟内存文件;

  • 分区:先使用gdisk在磁盘中分区出一个分区槽给系统作为swap
  • 格式化:利用建立swap格式的mkswap 设备文件名就能够格式化该分区槽成为swap格式
  • 使用:最后将该swap设备启动,即执行swapon 设备文件名命令
  • 观察:最终透过freeswapon -s指令来观察内存的使用情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# 步骤一:分区
gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): n
Partition number (7-128, default 7):
First sector (34-488397134, default = 468690944) or {+-}size{KMGTP}:
Last sector (468690944-488397134, default = 488397134) or {+-}size{KMGTP}: +512M
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 8200
Changed type of partition to 'Linux swap'

Command (? for help): p
Disk /dev/sda: 488397168 sectors, 232.9 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7B10AC68-EEE7-42BC-9088-3BB71109903A
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 488397134
Partitions will be aligned on 2048-sector boundaries
Total free space is 18659629 sectors (8.9 GiB)

Number Start (sector) End (sector) Size Code Name
1 2048 976895 476.0 MiB EF00 EFI System Partition
2 976896 2928639 953.0 MiB 0700
3 2928640 298627071 141.0 GiB 0700
4 298627072 454875135 74.5 GiB 0700
5 454875136 466593791 5.6 GiB 8200
6 466593792 468690943 1024.0 MiB 8300 Linux filesystem
7 468690944 469739519 512.0 MiB 8200 Linux swap

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.

partprobe

lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 232.9G 0 disk
├─sda1 8:1 0 476M 0 part /boot/efi
├─sda2 8:2 0 953M 0 part /boot
├─sda3 8:3 0 141G 0 part /home
├─sda4 8:4 0 74.5G 0 part /
├─sda5 8:5 0 5.6G 0 part
├─sda6 8:6 0 1G 0 part
└─sda7 8:7 0 512M 0 part
loop0 7:0 0 512M 0 loop /data/file
# 步骤二:创建swap格式
mkswap /dev/sda7
正在设置交换空间版本 1,大小 = 524284 KiB
无标签,UUID=d9ac2104-0e8c-426b-8fa2-3cfa7277b4a7

blkid /dev/sda7
/dev/sda7: UUID="d9ac2104-0e8c-426b-8fa2-3cfa7277b4a7" TYPE="swap" PARTLABEL="Linux swap" PARTUUID="2c266025-b487-4e20-b60e-9ee1d81a3ae6"

# 观察
free
total used free shared buff/cache available
Mem: 16137536 491500 15025276 17268 620760 15359456
Swap: 0 0 0

#步骤三:启动
swapon /dev/sda7

free
total used free shared buff/cache available
Mem: 16137536 492168 15024356 17268 621012 15358784
Swap: 524284 0 524284

# 步骤四:观察
swapon -s
文件名 类型 大小 已用 权限
/dev/sda7 partition 524284 0 -2

若实体分区槽无法支持的情况下,可使用创建一个大文件loop的方式创建swap,可通过swapoff命令卸载swap分区槽:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用dd命令在/tmp下新增一个128MB的文件
dd if=/dev/zero of=/tmp/swap bs=1M count=128
# 使用mkswap将/tmp/swap这个文件格式化为swap的文件格式
mkswap /tmp/swap
# 使用swapon来将/tmp/swap启动
swapon /tmp/swap
# 使用swapoff关掉swap file并设定自动启用
nano /etc/fstab
/tmp/swap swap swap defaults 0 0

swapoff /tmp/swap /dev/vda6
swapon -a
swapon -s

整个文件系统中包括superblock, inode table与其他数据等其实都会浪费磁盘容量,当在/dev/sda6和/dev/sda7建立起xfs/ext4文件系统时,一挂载就立刻有很多容量被用掉了;使用ls -l去查询某个目录下的数据时,第一行会出现一个total的字样,即该目录下的所有数据所耗用的实际block数量乘以block大小的值,etc目录虽然仅有8K但其消耗的内存总量确是12K;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ll -sh
总用量 32K
0 lrwxrwxrwx. 1 root root 7 1月 24 2022 bin -> usr/bin
4.0K dr-xr-xr-x. 5 root root 4.0K 1月 1 20:38 boot
4.0K drwxr-xr-x. 20 root root 4.0K 1月 1 20:38 data
0 drwxr-xr-x 3 root root 18 12月 26 22:19 data1
0 drwxr-xr-x 3 root root 17 12月 26 22:26 data2
0 drwxr-xr-x 19 root root 3.3K 1月 1 21:00 dev
12K drwxr-xr-x. 149 root root 8.0K 1月 1 20:42 etc
0 drwxr-xr-x. 5 root root 50 7月 31 2022 home
0 lrwxrwxrwx. 1 root root 7 1月 24 2022 lib -> usr/lib
0 lrwxrwxrwx. 1 root root 9 1月 24 2022 lib64 -> usr/lib64
0 drwxr-xr-x. 2 root root 6 4月 11 2018 media
0 drwxr-xr-x. 2 root root 6 4月 11 2018 mnt
0 drwxr-xr-x. 6 root root 59 8月 6 2022 opt
0 dr-xr-xr-x 214 root root 0 1月 2 2024 proc
4.0K dr-xr-x---. 12 root root 4.0K 1月 1 20:37 root
0 drwxr-xr-x 41 root root 1.3K 1月 1 21:16 run
0 lrwxrwxrwx. 1 root root 8 1月 24 2022 sbin -> usr/sbin
0 drwxr-xr-x. 2 root root 21 1月 1 20:17 srv
0 dr-xr-xr-x 13 root root 0 1月 2 2024 sys
4.0K drwxrwxrwt. 12 root root 4.0K 1月 1 20:58 tmp
0 drwxr-xr-x. 13 root root 155 1月 24 2022 usr
4.0K drwxr-xr-x. 21 root root 4.0K 1月 23 2022 var