本次培训内容将从Linux系统中的文件存储结构开始,讲述文件系统层次化标准(FHS,Filesystem Hierarchy Standard)、udev硬件命名规则以及硬盘分区的规划方法。
一、一切从"/"开始
在Linux系统中,目录、字符设备、块设备、套接字、打印机等都被抽象成了文件,存放于Linux系统中的各个目录中。Linux系统中的一切文件都是从"根(/)"目录开始的,并按照文件系统层次化标准(FHS)采用树形结构来存放文件,同时也定义了常见目录的用途。要注意的是,Linux系统中的文件和目录名称是严格区分大小写的,且文件名称中不得包含斜杆(/)。
Linux系统中的文件存储结构如下图所示:
Linux系统的文件存储结构可以用于指导我们把文件保存到相应的位置,以及告诉用户应该在哪里找到所需的文件。但是,并没有强制规定文件应该保存在哪个位置,FHS对于用户来说更多是一种道德上的约束。Linux系统中常见的目录名称以及所对应的存放内容,如下表所示(经常使用的目录已加粗):
Linux系统中还有一个重要的概念——路径。路径可以定位某个文件的具体位置,分为绝对路径和相对路径。绝对路径是指从根目录(/)开始直至具体的文件名称,而相对路径从当前所在的位置直至具体的文件名称。以编辑网卡配置文件为例,介绍绝对路径和相对路径的区别:
[root@linuxprobe ~]# vim /etc/sysconfig/network-scripts/ifcfg-eno16777728 //以绝对路径来定位配置文件
[root@linuxprobe sysconfig]# vim network-scripts/ifcfg-eno16777728 //以相对路径来定位配置文件
二、物理设备的命令规则
Linux系统内核中的udev设备管理器会自动把硬件名称规范起来,目的是为了让用户通过文件的名字可以猜出设备大致的属性以及分区信息等。在Linux系统中常见的硬件设备的文件名称如下表所示:
硬件设备 | 文件名称 |
IDE设备 | /dev/hd[a-d] |
SCSI/SATA/U盘 | /dev/sd[a-p] |
软驱 | /dev/fd[0-1] |
打印机 | /dev/lp[0-15] |
光驱 | /dev/cdrom |
鼠标 | /dev/mouse |
磁带机 | /dev/st0或/dev/ht0 |
现在的IDE设备已经很少用了,所以一般的设备都会以"/dev/sd"开头。由于一台主机可以有多块硬盘,因此系统采用a~p来代表16块不同的硬盘(默认从a开始分配),而且硬盘的分区编号也很有讲究:
- 主分区或扩展分区的编号从1开始,到4结束;
- 逻辑分区从编号5开始。
我们可以分析一下/dev/sda5这个设备文件的名称所包含的信息,一言以蔽之,"/dev/sda5"表示这是系统中第一块被识别的硬件设备中,分区编号为5的逻辑分区的设备文件。如下图所示:
一块硬盘设备最多只能创建4个主分区,为了解决分区数量不够的问题,用户一般选择使用3个主分区加一个扩展分区的方法,然后在扩展分区中创建出数个逻辑分区,从而来满足多分区的需求。如下图所示:
注意:所谓扩展分区,严格地来讲它不是一个实际意义的分区,它仅仅是一个指向下一个分区的指针,这种指针结构将形成一个单向链表。
三、挂载硬件设备
用户在硬盘存储设备上执行的文件建立、写入、读取、修改、转存与控制等操作都是依靠文件系统来完成的。文件系统的作用是合理规划硬盘,以保证用户正常使用需求。
在拿到一块新的硬盘后,首先需要进行分区,然后再格式化文件系统,最后才能挂载并正常使用。硬盘的分区取决你的需求以及硬盘大小,也可以不对硬盘进行分区(即整个硬盘作为一个分区),但是必须对硬盘进行格式化处理。
1、添加一块新的硬盘
第一步:编辑虚拟机设置
第二步:选择添加的硬件类型为"硬盘"
第三步:选项SCSI磁盘类型
第四步:创建新虚拟磁盘
第五步:最大磁盘大小设置为默认的20GB
第六步:点击完成
第七步:新磁盘添加成功,最后点击"确认"。
完成上述操作后,在虚拟机中就可以看到抽象成的设备文件了,按照udev服务命名规则,第二块被识别的设备应该被保存为/dev/sdb,如下所示:
[root@linuxprobe ~]# ls -l /dev/sd*
brw-rw----. 1 root disk 8, 0 Mar 10 19:57 /dev/sda
brw-rw----. 1 root disk 8, 1 Mar 10 19:57 /dev/sda1
brw-rw----. 1 root disk 8, 2 Mar 10 19:57 /dev/sda2
brw-rw----. 1 root disk 8, 16 Mar 10 19:57 /dev/sdb
2、给新硬盘进行分区
fdisk命令
用于管理磁盘分区,格式为"fdisk [磁盘名称]",与之前的命令不同,这条命令的参数是交互式的,相关参数以及作用如下所示:
参数 | 作用 |
m | 查看全部可用的参数 |
n | 添加新的分区 |
d | 删除某个分区信息 |
l | 列出所有可用的分区类型 |
t | 改变某个分区的类型 |
p | 查看分区信息 |
w | 保存并退出 |
q | 不保存直接退出 |
实验:使用fdisk命令对新硬盘/dev/sdb进行分区设置。在看到提示信息后输入参数p可以查看硬盘分区内已有的分区信息。
[root@linuxprobe ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x1894a517.
Command (m for help): p //查看硬盘内已有的分区信息
Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x1894a517
Device Boot Start End Blocks Id System
//目前该硬盘设备没有任何分区信息
Command (m for help):
第1步:输入参数n添加新的分区。系统会要求你继续输入参数p来创建主分区,还是输入参数e来创建扩展分区。这里输入参数p创建一个主分区。
Command (m for help): n //添加新的分区
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p //创建主分区
Partition number (1-4, default 1): 1 //输入主分区的编号
First sector (2048-41943039, default 2048): <此处按下回车健>
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-41943039, default 41943039): +5G //设置分区的大小为5GB
Partition 1 of type Linux and of size 5 GiB is set
第2步:再次输入p参数,可以看到一个名为/dev/sdb1的主分区。
Command (m for help): p
Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x1894a517
Device Boot Start End Blocks Id System
/dev/sdb1 2048 10487807 5242880 83 Linux //新建的分区信息,容量大小为5GB
第3步:最后输入参数w保存分区信息并退出。
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.
第4步:至此,一个名为/dev/sdb1的硬盘主分区(相当于window系统的D盘)创建成功。注意:若无法看到/dev/sdb1,可以执行partprobe命令手动将分区信息同步到内核。
[root@linuxprobe ~]# ls -l /dev/sd*
brw-rw----. 1 root disk 8, 0 Mar 10 19:57 /dev/sda
brw-rw----. 1 root disk 8, 1 Mar 10 19:57 /dev/sda1
brw-rw----. 1 root disk 8, 2 Mar 10 19:57 /dev/sda2
brw-rw----. 1 root disk 8, 16 Mar 10 20:52 /dev/sdb
brw-rw----. 1 root disk 8, 17 Mar 10 20:52 /dev/sdb1
3、格式化分区
在对硬盘进行分区化操作后,还需进行格式化操作,否则服务写入数据。mkfs命令用于对格式化操作,在输入mkfs后可以通过敲击两下tab健进行补齐,如下所示:
[root@linuxprobe ~]# mkfs mkfs mkfs.cramfs mkfs.ext3 mkfs.fat mkfs.msdos mkfs.xfs mkfs.btrfs mkfs.ext2 mkfs.ext4 mkfs.minix mkfs.vfat
将/dev/sdb1分区格式化为ext4文件系统,如下所示:
[root@linuxprobe ~]# mkfs.ext4 /dev/sdb1 mke2fs 1.42.9 (28-Dec-2013) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 327680 inodes, 1310720 blocks 65536 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=1342177280 40 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736 Allocating group tables: done Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done
4、挂载并使用
接下来就是挂载并使用存储设备了,挂载的目的就是为了使系统能够读取硬盘的数据。mount命令用来挂载文件系统,格式为"mount 文件系统 挂载目录",其中-a参数会自动检查/etc/fstab文件中有无疏漏被挂载的设备文件,如果有则进行自动挂载操作。设备的操作步骤也十分简单,具体步骤如下所示:
第1步:创建一个用于挂载设备的挂载点目录
[root@linuxprobe ~]# mkdir /newdisk
第2步:使用mount命令将存储设备与挂载点进行关联
[root@linuxprobe ~]# mount /dev/sdb1 /newdisk/
第3步:使用df -h命令来查看挂载状态和硬盘使用量信息
[root@linuxprobe ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 18G 3.1G 15G 18% /
devtmpfs 985M 0 985M 0% /dev
tmpfs 994M 80K 994M 1% /dev/shm
tmpfs 994M 8.8M 986M 1% /run
tmpfs 994M 0 994M 0% /sys/fs/cgroup
/dev/sr0 3.5G 3.5G 0 100% /media/cdrom
/dev/sda1 497M 119M 379M 24% /boot
/dev/sdb1 4.8G 20M 4.6G 1% /newdisk
注意:如果想要这个设备文件的挂载重启后依然生效,则需要把挂载的信息按照指定的格式写入到配置文件中。挂载信息的格式为:
设备文件 挂载目录 格式类型 权限选择 是否备份 是否自检
字段 | 意义 |
设备文件 | 一般为设备的路径+设备名称,也可以写唯一识别码(UUID,Universally Unique Identifier) |
挂载目录 | 指定要挂载到的目录,需在挂载前创建好 |
格式类型 | 指定文件系统的格式,比如Ext3、Ext4、XFS、SWAP、iso9660(此为光盘设备)等 |
权限选项 | 若设置为defaults,则默认权限为:rw, suid, dev, exec, auto, nouser, async |
是否备份 | 若为1则开机后使用dump进行磁盘备份,为0则不备份 |
是否自检 | 若为1则开机后自动进行磁盘自检,为0则不自检 |
[root@linuxprobe ~]# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Sat Feb 15 12:19:36 2020
#
# 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
#
/dev/mapper/rhel-root / xfs defaults 1 1
UUID=ba40f004-d75d-400f-b0e0-c4d395261e14 /boot xfs defaults 1 2
/dev/mapper/rhel-swap swap swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newdisk ext4 defaults 0 0
四、添加交换分区
SWAP(交换)分区是一种通过在硬盘中预先划分一定的空间,然后把内存中暂时不常用的数据临时存放到硬盘中,以便腾出物理空间让更活跃的程序服务来使用的技术,其设计的目的是为了解决真实物理内存不足的问题。毕竟硬盘设备的读写速度肯定比物理内存慢,所以只有在真实的物理内存耗尽后才会调用交换分区的资源。
交换分区的划分建议:在生产环境中,交换分区的大小一般为真实物理内存的1.5~2倍。
实验:将原本只有2GB的SWAP交换分区扩展至6GB。
(1)先创建一个大小为4GB的硬盘主分区
[root@linuxprobe ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (2-4, default 2): 2
First sector (10487808-41943039, default 10487808): <此处按下回车键>
Using default value 10487808
Last sector, +sectors or +size{K,M,G} (10487808-41943039, default 41943039): +4G
Partition 2 of type Linux and of size 4 GiB is set
Command (m for help): P
Disk /dev/sdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x1894a517
Device Boot Start End Blocks Id System
/dev/sdb1 2048 10487807 5242880 83 Linux
/dev/sdb2 10487808 18876415 4194304 83 Linux //最后记得按下w保存退出
(2)使用SWAP分区专用的格式化命令mkswap,对新建的主分区进行格式化操作。
[root@linuxprobe ~]# mkswap /dev/sdb2
Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=b655169e-b635-4c32-844b-1f8b0d970fd5
(3)使用swapon命令把准备好的SWAP分区设备正式挂载到系统中。
[root@linuxprobe ~]# free -h
total used free shared buffers cached
Mem: 1.9G 776M 1.2G 9.2M 1.8M 255M
-/+ buffers/cache: 519M 1.4G
Swap: 2.0G 0B 2.0G
[root@linuxprobe ~]# swapon /dev/sdb2
[root@linuxprobe ~]# free -h
total used free shared buffers cached
Mem: 1.9G 779M 1.2G 9.2M 1.8M 255M
-/+ buffers/cache: 522M 1.4G
Swap: 6.0G 0B 6.0G //SWAP分区扩展至6GB
(4)为了让新的交换分区设备重启后生效,需要将相关信息写入到配置文件中。
[root@linuxprobe ~]# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Sat Feb 15 12:19:36 2020
#
# 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
#
/dev/mapper/rhel-root / xfs defaults 1 1
UUID=ba40f004-d75d-400f-b0e0-c4d395261e14 /boot xfs defaults 1 2
/dev/mapper/rhel-swap swap swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newdisk ext4 defaults 0 0
/dev/sdb2 swap swap defaults 0 0
五、磁盘容量配额
Linux系统的设计初衷就是为了满足多人同时使用并执行各自的任务,但是硬件资源是固定且有限的,不能让用户无限制地使用系统资源。针对这种情况,root管理员就需要使用磁盘容量配额服务来限制某位用户或某个用户组针对特定文件夹可以使用的最大硬盘空间或最大文件个数。可以使用quota命令进行磁盘容量配额管理,其中限制用户又可分为软限制和硬限制。
- 软限制:当达到软限制时会提示用户,但仍允许用户在限定的额度内继续使用;
- 硬限制:当达到硬限制时会提示用户,且强制终止用户的操作。
RHEL7系统中已经安装了quota磁盘容量配额服务程序包,但存储设备默认没有开启对quota的支持,此时需要手动编辑配置文件。
实验:让/boot目录能够支持quota磁盘配额技术。
[root@linuxprobe ~]# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Sat Feb 15 12:19:36 2020
#
# 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
#
/dev/mapper/rhel-root / xfs defaults 1 1
UUID=ba40f004-d75d-400f-b0e0-c4d395261e14 /boot xfs defaults,uquota 1 2
/dev/mapper/rhel-swap swap swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newdisk ext4 defaults 0 0
[root@linuxprobe ~]# reboot //重启系统
[root@linuxprobe ~]# mount | grep boot
/dev/sda1 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,usrquota) //目录/boot已经支持quota磁盘配额技术了
1、xfs_quota命令
是一个专门针对XFS文件系统来管理quota磁盘容量配额服务而设计的命令,其格式为"xfs_quota [参数] 配额 文件系统"。
实验:设置tom用户对/boot目录的quota磁盘容量配额。具体限制包括:磁盘使用量的软限制和硬限制分别为3MB和6MB;创建文件的软限制和硬限制分别为3个和6个。
[root@linuxprobe ~]# useradd tom //新建一个tom用户
[root@linuxprobe ~]# chmod -Rf o+w /boot/ //给其他用户增加写权限
[root@linuxprobe ~]# xfs_quota -x -c 'limit bsoft=3m bhard=6m isoft=3 ihard=6 tom' /boot/
[root@linuxprobe ~]#
[root@linuxprobe ~]# xfs_quota -x -c report /boot/
User quota on /boot (/dev/sda1)
Blocks
User ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
root 95344 0 0 00 [--------]
tom 0 3072 6144 00 [--------]
在完成上述的软硬限制配置后,切换至tom用户并尝试创建一个大小为5MB和8MB的文件。
[root@linuxprobe ~]# su - tom //切换至tom用户
[tom@linuxprobe ~]$ dd if=/dev/zero of=/boot/testfile bs=5M count=1
1+0 records in
1+0 records out
5242880 bytes (5.2 MB) copied, 0.00450163 s, 1.2 GB/s
[tom@linuxprobe ~]$ dd if=/dev/zero of=/boot/testfile_1 bs=8M count=1
dd: error writing ‘/boot/testfile_1’: Disk quota exceeded //在尝试创建8MB的文件时,提示超出磁盘限制
1+0 records in
0+0 records out
1048576 bytes (1.0 MB) copied, 0.0032066 s, 327 MB/s
2、edquota命令
用于编辑用户的quota配额限制,格式为"edquota [参数] 用户",可以使用edquota命令按需修改限额的数值。其中,-u参数表示要针对哪个用户进行设置;-g参数表示要针对哪个用户组进行设置。edquota命令会调用Vim编辑器。
实验:把用户tom的硬盘使用量的硬限制从5MB提升至8MB。
[root@linuxprobe ~]# edquota -u tom
Disk quotas for user tom (uid 8889):
Filesystem blocks soft hard inodes soft hard
/dev/sda1 8192 3072 8192 2 3 6
[root@linuxprobe ~]# su - tom
[tom@linuxprobe ~]$ rm /boot/tom/* //先清空文件夹内的数据
[tom@linuxprobe ~]$ dd if=/dev/zero of=/boot/tom/testfile_1 bs=8M count=1 //文件写入成功
1+0 records in
1+0 records out
8388608 bytes (8.4 MB) copied, 0.0267005 s, 314 MB/s
[tom@linuxprobe ~]$ dd if=/dev/zero of=/boot/tom/testfile_1 bs=10M count=1 //文件写入失败
dd: error writing ‘/boot/tom/testfile_1’: Disk quota exceeded
1+0 records in
0+0 records out
8388608 bytes (8.4 MB) copied, 0.019888 s, 422 MB/s
六、软硬件方式链接
在Linux系统中存在着硬链接和软连接两种文件:
硬链接(hard link):可以理解为一个"指向原始文件的inode的指针",系统不为它分配独立的inode和文件。所以,硬链接文件与原始文件其实是同一个文件,只是名字不同。每添加一个硬链接,该文件的inode连接数就会增加1;而且只有当该文件的inode连接数为0时,才算将他彻底删除。注意:不能跨分区对目录文件进行链接。
软链接(也称为符号链接[symbolic link]):仅仅包含所链接文件的路径名,因此能链接目录文件,也可以跨越文件系统进行链接。但是当原始文件被删除后,链接文件也将失效,这点类似windows系统中的"快捷方式"。
ln命令
用于创建链接文件,格式为"ln [选项] 目标",在使用ln命令的时候要注意是否添加-s参数,相关参数以及作用如下所示:
参数 | 作用 |
-s | 创建"软链接"(如果不带-s参数,则默认创建硬链接) |
-f | 强制创建文件或目录的链接 |
-i | 覆盖之前,先询问 |
-v | 显示创建链接的过程 |
实验1:给readme.txt文件创建一个硬链接。
[root@linuxprobe ~]# echo "hello world" > readme.txt
[root@linuxprobe ~]# ln readme.txt readln.txt //创建硬链接文件readln.txt
[root@linuxprobe ~]# cat readln.txt
hello world
[root@linuxprobe ~]# ls -l readme.txt
-rw-r--r--. 2 root root 12 Mar 11 20:31 readme.txt //原始文件的inode连接数增加至2
[root@linuxprobe ~]# rm readme.txt //删除原始文件
rm: remove regular file ‘readme.txt’? y
[root@linuxprobe ~]# cat readln.txt //依然可以读取硬链接文件
hello world
实验2:给readme.txt文件创建一个软连接。
[root@linuxprobe ~]# echo "hello world" > readme.txt
[root@linuxprobe ~]# ln -s readme.txt readln.txt //创建一个软链接文件readln.txt
[root@linuxprobe ~]# cat readln.txt
hello world
[root@linuxprobe ~]# ls -l readln.txt
lrwxrwxrwx. 1 root root 10 Mar 11 20:35 readln.txt -> readme.txt //相当于一个指针指向readme.txt文件
[root@linuxprobe ~]# rm -f readme.txt //删除原始文件
[root@linuxprobe ~]# cat readln.txt
cat: readln.txt: No such file or directory //读取软链接文件失败