Linux:硬盘管理与文件系统
Preliminaries
请确保您对
cd
、ls
等命令有了一定的了解,懂得使用--help
参数,如ls --help
查看所有命令的详细参数和使用帮助。
本文将可能会用到以下命令:
- 基本操作:
cd
、ls
、rm
、mkdir
、rmdir
、pwd
- 文件创建、复制、移动删除:
touch
、cp
、mv
、rm
- 文件权限管理:
chmod
、chown
、umask
- 文件查看、读写:
vi
、vim
、gedit
、cat
- 文件检索:
find
、whereis
、which
- 用户管理:
useradd
、usermod
、groupadd
- 磁盘管理:
mount
、umount
、df
、blkid
、fdisk
、ln
您并不需要立刻掌握它们,但在本文中它们将可能会被用到,所以看完本文你将会学会这些指令的部分用法。
文件系统
Linux是基于多用户的系统,若管理不当,很容易造成文件的损坏等问题。因此文件系统值得进行学习和记录:
- 文件的权限管理
- Linux的目录配置、各个目录的意义等
注:由于部分内容需要权限才能操作,因此下文所有命令默认情况下均在root用户下进行操作。
- 使用
su root
命令可以切换到root用户。
Linux系统的文件属性
使用cd /
切换到主目录,键入命令ls -l
,会得到以下内容:
1 | (以下数据在 "ubuntu 16.04 STL" 得到) |
各列意义分别为:<文件权限> <链接数> <所属拥有者> < 所属用户组> <文件大小> <修改日期 月:日:(年)-时:分:> <文件名>
。
① 文件权限(permission)
此处显示的Linux的文件权限是一个10位的字符串,分为一个文件类型标识符和三组权限标识符,每组权限标识符有三位(rwx
):
- 以
dev
文件为例,其首位为【d】,表示这是一个目录(directory)——【d】【l】【-】【b】【c】分表表示“目录”、“链接”(link)、“文件”、“任意读写设备”(block)和“串口设备”(character)。
又例如,
cd /dev
查看sda
文件的文件属性,会发现这是一个【b】文件。在Linux中,这是首位挂载的SATA硬盘,将在下文进行进一步的解读。
- 权限标识符分为三种【r】(read,权限代值为4)、【w】(write,权限代值为2)、【x】(execute,权限代值为1)。
- 一共有三组权限标识符。这三组权限标识符从左到右分别标示出了文件所有者、同用户组用户和其它人的权限。
如上文所显示的
boot
文件,它是一个目录,对于所有者root
具有【rwx】(读写与执行)权限,对root
用户组具有【rx】(读和执行),其它用户对其可以【rx】。
- 需要注意的是,root用户对所有文件具有完全权限。也就是说root文件不受文件权限属性的限制。
- 目录和文件的
rwx
并不具有相同的意义,如对于一个文件test.sh
,【r】权限表示其可以通过vi test.sh
打开并读取、【x】权限可以利用./test.sh
直接执行;对于一个目录test
,【r】权限指的是目录子文件读取,如ls
指令、【x】权限实际上指的是目录访问(access directory),如cd ./test
。
② 文件链接(link file)
文件属性的第二列表示有多少个文件链接到这个文件节点(inode),这部分内容跟Linux的软连接和硬链接有关。将在下文中进行解释。
Linux系统中的文件权限管理
本节将会介绍三种命令chmod
、chown
、chgrp
。
chgrp
是change group的缩写,即改变文件所属用户组,我们使用chgrp --help
查看帮助:
1 | 用法:chgrp [选项]... 用户组 文件... |
1 | 示例: |
-
chown
的用途相当广,某种程度上可以直接替换chgrp
指令。使用示例:chown -R user:usergroup /test
可以把文件/test
的所属用户和用户组修改为user
和usergroup
,【-R】参数可以一并修改该目录下的所有文件。 -
chmod
用于修改文件权限,支持一系列的正则匹配方式。用的更多的方式是使用权限代值的方式修改文件权限:chmod 735 /test
表示分别赋予权限【rwx】【-wx】【r-x】给用户、用户组和其他人。
权限代值:r=4、w=2、x=1;如果要赋予用户【rwx】的权限,即: 4+2+1=7,首位填7。
chmod
还支持正则的操作方式,如chmod u=rwx,go=rx
就会赋予权限【rwx】【r-x】【r-x】。
即chmod [options] <范围><操作符><权限符>[,<范围><操作符><权限符>... ] <文件或目录>
。
chmod指令的正则Mode表
范围 | 操作符 | 权限符 |
---|---|---|
【u】(用户)、【g】(用户组)、【o】(其他人)、【a】(所有人) | 【+】(添加)、【-】(减去)、【=】(设置) | 【r】【w】【x】 |
文件目录与配置、管理
① Filesystem Hierachy Standard(FHS)
因为Linux是一个多用户系统,为了方便更多的用户能够较好的协同,对文件的存放做出了规定,即FHS。概览如下:
可分享(shareable) | 不可分享(unshareable) | |
---|---|---|
不变(static) | /usr(软件) | /etc(配置文件) |
/opt(第三方辅助软件) | /boot(内核与部署文件) | |
可变动(variable) | /var/mail(邮箱) | /var/run(程序脚本相关【PID】) |
/var/spool/news(新闻组) | /var/lock(程序单线程运行相关) |
根目录存放标准:
目录 | 应放置文件目录 |
---|---|
/bin | 存放可执行文件的目录,如chmod 、cat 等 |
/boot | Linux内核及其它启动文件 |
/dev | 硬件接口相关的文件存放于此,如/dev/sda |
/etc | 系统主要的配置文件,如/etc/passwd 、etc/fstab 等 |
/lib | 系统启动时及/bin 中可执行文件会用到的函数库 |
/media | 可删除的设备,如软盘、光盘等 |
/mnt | 临时挂载到系统的文件 |
/opt | 第三方辅助软件,即非发行版中对某功能所原生提供的软件 |
/run | 系统启动时的各项程序脚本信息 |
/sbin | 类似/bin ,但这些脚本命令一般只有root 用户配置整个系统时才会用到,如fdisk 、ifconfig 等 |
/srv | 网络服务的数据存放目录 |
/tmp | 程序存放临时数据的目录 |
/usr | 软件存放目录,详见下文 |
/var | 可变数据的存放目录,详见下文 |
/home | 每个用户的主目录 |
/lib |
存放与/bin 中文件格式不同的二进制文件,如64位数的库文件等 |
/root | root 用户的主目录 |
UNIX Software Resource(/usr):
目录 | 应放置文件目录 |
---|---|
/usr/bin | 所有一般用户都能执行的程序文件,发行版中基于/bin 的文件通过链接会在该文件下都存在一份 |
/usr/lib | 同上 |
/usr/local | 系统管理员在本机安装的软件,一般时为了避免版本差异。如/bin 中自带了python 2.7 ,你可以在此处存一份python 3.6 的版本 |
/usr/sbin | 非系统正常运行所需要的程序命令文件 |
/usr/share | 存放可分享的只读文件,如/usr/share/man 存放在线帮助文件、/usr/share/doc 存放软件的说明文档等 |
/usr/src | 代码文件 |
/usr/games | 游戏文件 |
/usr/include | C语言头文件 |
/var:
目录 | 应放置文件目录 |
---|---|
/var/cache | 程序运行过程中的缓存 |
/var/lib | 程序运行过程中的依赖数据文件目录 |
/var/lock | 程序运行过程中严格限制单线程使用的文件 |
/var/log | 日志文件 |
/var/mail | 邮箱文件 |
/var/run | 程序运行后产生的PID会存放于此 |
/var/spool | 队列数据,常用于跨程序调用时的缓存队列 |
② 文件目录管理
相对路径与绝对路径、路径标识符:
1 | . 当前层目录 |
如,存在一个用户名为
user
的用户,执行cd ~
命令将会进入到/home/user
目录中、ls .
将会列出当前目录所有的文件。
目录操作命令:
cd
切换目录,如cd /
。其为【change directory】的缩写。pwd
显示当前工作目录的绝对路径,其为【print working directory】的缩写。mkdir
创建一个目录,如mkdir /data
将会在根目录下创建一个/data
文件夹。rmdir
移除一个空目录。如果为非空目录,建议使用rm -rf /data
来移除一个非空目录/data
。
③ 文件的创建、复制、删除与移动
touch
实际上是修改文件的时间与日期,但经常用于创建一个新文件,如touch ./newfile.txt
cp
复制文件,如把当前层级的文件A移动到根目录下:cp A /
。常用的参数【-p】,表示连文件的权限一同拷贝过去;【-r】用于把一个目录及目录里的子文件一同拷贝;【-i】如果目标地址已存在,会进行确认操作的询问。rm
删除文件。常用的如【-rf】,用于不询问的删除整个目录文件(由于该操作比较危险,请谨慎操作)。mv
移动文件,相当于Windows中的剪切操作。
此处再补充一个指令:
umask
用于指定、查看当前用户创建一个新文件时的默认权限。
键入umask -S
:
1 | u=rwx,g=rwx,o=rx |
对应的键入umask
:
1 | 0002 |
意思就是【others】缺了【w】(权限代值为2)。
使用命令umask 0022
修改默认权限,再使用 umask -S
查看所设定的默认权限:
1 | u=rwx,g=rx,o=rx |
④ 文件的查找
which
命令可以查找一个可执行文件/脚本的位置,如which ls
find
可以在指定的目录中搜寻文件,如find /bin -name ls
;该命令功能比较强大,可用【–help】查看详细的参数,此处不赘述,常用的指令如【-name】可以指定目标文件的名字。whereis
该命令相较于find
功能更简单,但速度较快,使用较简单;常用的参数如【-l】,可以指定要搜索的目录等。
⑤ 环境变量 $PATH
假如我有一个可执行文件存放在/usr/mybin
中,我每次执行它时都要cd
到这个文件夹然后再执行,就非常麻烦。在Windows中我们可以通过设置环境变量来告诉系统哪些路径下的文件是Shell的一级搜索目录,同样在Linux也有这个功能。
我们可以通过echo $PATH
命令来查看环境变量:
1 | /home/user/bin:/home/user/.local/bin:/data/public/env/anaconda3/bin |
可以观察到其包含了多组环境变量,用【:】隔开来。对于每个用户在其主目录下都有一个.bashrc
文件用以配置环境变量,我们可以通过vim ~/.bashrc
来查看该文件,并通过
1 | export $PATH=xxxxx:xxxxxx:xxxxxx |
来设置环境变量。设置完毕后直接reboot
重启系统或source ~./bashrc
编译该文件即可刷新系统的环境变量。
文件链接
① 索引式文件系统
在Linux中常用的ext2/3/4文件系统格式中,inode记录了某个文件其数据在硬盘中实际存放的区块。相比FAT格式的文件系统,inode能够让硬盘更快的检索到文件数据,某种程度上避免了频繁进行磁盘碎片整理的需求。
inode的数据存储方式被称为索引式文件系统(index allocation),每个文件会申请使用一个inode号,该inode指向的硬盘区块记录了文件数据的所有存储区块和存储顺序,操作系统就能凭此一次性读取所有的数据。
1 | (以下数据在 "ubuntu 16.04 STL" 得到) |
相对的,还会有一个超级区块(Super Block),记录了系统中所有已使用和未使用的inode号,根据ext2/3/4的不同,每个inode占位从128B到256B。
可以使用dumpe2fs
指令查看ext文件系统的超级区块信息,如:sudo dumpe2fs /dev/sda
。(如果硬盘较大,可以使用Crtl+z
或Ctrl+c
提前结束程序)
1 | .......(略) |
正因为有了inode,我们常说的【挂载】(mount)才有了意义。本质上,挂载操作是在向系统申请inode,通过给每个文件和目录分配inode,操作系统依靠inode寻找文件和鉴权,我们才能正常操作Linux系统。
② 硬链接与软(符号)链接
- 软(符号)链接(Symbolic Link) 类似于Windows中的桌面快捷链接,它本身就是一个独立的文件,自身占用一个inode,但inode指向的数据是链接原文件的区块位置。
- 硬链接(Hard Link) 与链接源文件占用了同一个inode,它本身知识在某个目录下新加了一条指向原inode的关联记录。
为了更好地分辨这两种链接方式的区别,我们进行以下操作:
- 使用
touch a.txt
指令创建一个新文件a.txt
,并使用vim a.txt
将该文件的内容改为字符串 "数据 "。(关于Vim的使用请查看帮助文档) - 使用
ls -li
和cat a.txt
查看相关内容,注意观察其inode号(926162 )和链接数(=1):
1 | (base) root :~/test$ ls -li |
- 使用
ln a.txt hardlink_a
创建一个硬链接,使用ls -li
查看,可以看到二者inode号一致、文件大小皆为 且链接数皆变为了 :
1 | (base) root :~/test$ ls -li |
- 使用
ln -s a.txt symlink_a
创建一个软链接,使用ls -li
查看,可以看到软连接有自己的inode号,且不影响源文件的链接数,且文件大小也不一致:
1 | (base) root :~/test$ ls -li |
- 使用
cat a.txt
、cat harlink_a
、cat symlink_a
会发现三者内容完全一致。现在修改a.txt
中的内容为" 修改后的数据 ",然后查看三个文件的内容,三者内容同样一致。同样的,vim hardlink_a
或vim symlink_a
一样会修改同样的数据区,cat
出来的内容也是相同的。 - 使用
rm a.txt
删除原文件,再使用cat
指令打开两个链接文件,会发现软连接已经打不开了,而硬链接仍然可以打开。
- 那么,软连接和硬链接的区别又在何处呢?
事实上,硬链接得到的文件会与原文件保持样的数据尺寸(但并不意味着复制了一份原数据)、一样的数据权限、一样的inode号,没有额外的区块和inode占用消耗,一定程度上可以防止区块数据和inode被意外释放;而软连接申请了新的inode,并占用了一定的区块数据(数据量取决于原文件名,如a.txt
共五个字符,则占用5B),当原文件被删除,软连接也就无法打开了,这跟Windows中的表现是一致的。
(在Linux中,如果区块数据没有任何一个inode链接到,则可以认为这些区块已经被释放)
硬盘管理
认识硬盘
现代硬盘主要由柱头和碟片组成。为了高速的读写磁盘,人们设计了 MBR(Master Boor Record) ;随着硬盘容量的变大,2TB以上的硬盘采用 GPT(GUID partition table) 作为分区格式。这里主要介绍MBR。
Linux通过把硬件当成一个文件的方式管理硬盘,如计算机挂载的第一个机械硬盘的文件地址为:/dev/sda
。
在MBR格式中,我们将MBR称为主引导记录,用于引导系统的启动。如果你尝试在一个硬盘中建立一个多操作系统的软件目录,会经常接触到MBR的内容。MBR的大小为448字节,它和 分区表(partition table) 组成了第一个扇区,分区表的大小为64KB,即第一个扇区的大小为512KB。
- 相对的,GPT第一个扇区有4K字节,因此能够引导更大的磁盘。
我们常说的分区,实际上只对分区表进行操作,同时只能记录划分为四组分区记录。但显然我们在Windows中常常用的硬盘分区多于4个区,这就要提到扩展分区和逻辑分区了:
- 主要分区与扩展分区由于MBR格式的限制,它们合起来[最多]只能有四个;
- 扩展分区在Linux中只能存在一个,它指向主要分区之外的区域,在区域中存在扩展分区的分区表,该表不受64KB的限制,因此可以指向很多个逻辑分区,即所有的逻辑分区组成了扩展分区。
换句话说,受限于操作系统,以MBR格式为例,若一块硬盘设置了两个主分区,则一个硬盘的分区组成为:
MBR 448KB | 分区表64KB | |||||
---|---|---|---|---|---|---|
主分区1 | 主分区2 | 扩展分区 | ||||
(原)主分区3 | (原)主分区4 | |||||
逻辑分区1 | .......... | 逻辑分区n |
系统启动引导:BIOS与UEFI
对于常装机的朋友来说,BIOS与UEFI并不陌生。这里只简单介绍:
- BIOS是写入固件程序,这里所说的固件指的是主板。因此BIOS是系统启动时第一个执行的程序,它会主动求搜寻MBR,然后按照引导信息去搜寻操作系统软件内容,最后启动我们所熟悉的操作系统。
- UEFI使用C语言写成(相对的BIOS基本是由汇编写成),为了解决BIOS的一些缺点而提出;相对于写入固件的BIOS,它不需要第三方厂商支持就能部署,甚至在启动阶段就可以直接通过TCP/IP协议连上互联网,而不需要操作系统再次操作网卡硬件。某种意义上UEFI就是一个低级的操作系统。
硬盘状态查看
df
指令可以查看磁盘的使用量,为了方便阅读,常使用【-h】指令以GB为单位显示数据,用【-T】列出文件系统:
1 | (base) root :~$ df -hT |
硬盘分区、格式化、检验与挂载
① 分区与格式化
使用lsblk
(list block device的缩写)命令可以查看磁盘及其分区的列表:
1 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT |
- 使用
fdisk
和gdisk
可以分别在MBR及GPT文件系统上进行分区。这些命令都比较简单,按照相应的提示步骤操作即可。(可以试使用fdisk -l
来查看硬盘的文件系统)。>fdisk参考使用流程< - 使用
mkfs.???
指令进行格式化:如果我们想把硬盘格式化为ext4格式,则使用mkfs.ext4
进行格式化操作,相应的还有mkfs.xfs
等命令。如mkfs.ext4 /dev/sda
。
② 磁盘挂载与卸载
使用mount /dev/sda /data
可以把设备/dev/sda
挂载到/data
目录下。
然而每次重新开机挂载信息就会丢失,所以我们需要把挂载信息写入/etc/fstab
文件中:
- 首先,使用
blkid
命令查看硬盘的UUID。 - 使用
vim /etc/fstab
打开配置文件,在文末添加一行:
<fs spec> <fs file> <fs vfstype> <fs mntops> <fs freq> <fs passno>
,如UUID=06c17b55-521c-470d-aceb-69ab9be10e4b /data ext4 defaults 0 2
,具体配置内容参考下表。
值名 | 值说明 |
---|---|
fs spec | 分区定位,可以给UUID或LABEL,例如:UUID=06c17b55-521c-470d-aceb-69ab9be10e4b 或LABEL=software |
fs file | 挂载点地址,如/data |
fs vfstype | 系统格式 |
fs mntops | 挂载参数,详见下 |
fs freq | 磁盘备份,默认为0,表示不需要dump操作 |
fs passno | 磁盘检查顺序,填0时表示不检测。大于0时,1 是root文件系统保留位,之后的数字越大检查顺序越靠后 |
参数值 | 值说明 |
---|---|
auto | 系统自动挂载,fstab默认就是这个选项 |
defaults | rw, suid, dev, exec, auto, nouser, and async. |
noauto | 开机不自动挂载 |
nouser | 只有超级用户可以挂载 |
ro | 按只读权限挂载 |
rw | 按可读可写权限挂载 |
user | 任何用户都可以挂载 |
请注意光驱和软驱只有在装有介质时才可以进行挂载,因此它必需填写noauto
mount -a
可以按/etc/fstab
的配置挂载所有硬盘,一般也用来检测挂载配置的正确性。
- 使用
umount /dev/sda
可以将各个挂载的设备卸载。
Gitalking ...