文件系统是学习Linux的一个十分基础的知识,同时也是学习Linux的一个必备知识。本文将站在“上帝视角”对整个文件系统进行进行详细的讲解,主要内容包括文件系统结构元素的组成、文件管理相关命令的使用以及软连接和硬链接的介绍。
一、文件系统结构元素的组成
大家都知道程序是由指令加数据组成。数据分为元数据和数据。元数据用来存储文件的属性信息,保存在inode节点中,数据则保存在block中。而文件系统是对一个存储设备上的数据和元数据进行组织的机制。
linux系统文件系统通过使用一组通用的 API 函数,把几乎所有的资源抽象为文件的形式,即我们所说的“一切皆文件”。例如,read 函数调用可以从指定的文件描述符读取一定数量的字节。read () 函数调用可以从指定的文件描述符读取一定数量的字节。open() 函数调用可以从指定的文件描述符打开文件。write()函数调用可以在指定的文件描述符中写入数据。close()函数调用可以关闭指定的文件。
1.文件系统目录标准(FHS)
Filesystem Hierarchy Standard(文件系统目录标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。在Linux中,所有的文件与目录都由根目录/ 开始。那是所有目录与文件的源头。然后再一个一个分支下来,有点像树状。因此,我们也称这种目录配置方式为:“目录树(directory tree)”。
[[email protected] ~]#tree -L 1 //├── bin -> usr/bin├── boot├── dev├── etc├── home├── lib -> usr/lib├── lib64 -> usr/lib64├── media├── mnt├── opt├── proc├── root├── run├── sbin -> usr/sbin├── srv├── sys├── tmp├── usr├── var└── web
这个目录树主要特性有:
目录树的起始点为根目录(/, root)。
每一个目录不仅能使用本地端分区的文件系统,也可以使用网络上的文件系统。举例来说,可以利用网络文件系统(Network File System,NFS)服务器载入某特定目录等。
每一个文件在此目录树中的文件名(包含完整路径)都是独一无二的。
2.文件的路径表示
绝对路径为:由根目录(/)开始写起的文件名或目录名称,例如/home/dmtsai/.bashrc。
相对路径为相对于当前路径的文件名写法。
.:表示当前目录,也可以使用./来表示。
..:表示上一层目录,也可以../来表示。
3.文件命名法则
文件是磁盘上的一段存储空间中存储的数据,它通常基于文件名引用文件;故我们要做到按名存取,知名见义。
严格区分字符大小写;
目录是文件的路径映射,从本质上来说也是文件,在同一个路径下,两个文件不能同名;
支持使用除/以外的所有字符;但不建议使用特殊字符命名文件;
最长不能超过255个字符。
4.文件系统结构详解
/bin:所有用户可用的基本命令程序文件;
/sbin:实现管理功能的程序文件;
/boot:引导加载器的静态文件;内核、ramdisk(initrd, initramfs)文件亦在此处;能独立分区
/dev:存储特殊文件或设备文件;
/etc:系统和应用程序的配置文件;
/home:普通用户的家目录;能独立分区。每个都有自己专用的家目录;
/root:管理员的家目录;
/lib:共享库文件,以内核模块文件;不能独立分区
/lib64:64位系统特有的存放64位共享库的路径;不能独立分区
/media:挂载便携式设备;
/mnt:挂载临时文件系统;
/opt:第三方应用程序的安装路径(Add-on software packages);
/srv:当前系统提供的服务运行中的用到的中间数据(Data for services provided by this system);
/tmp:临时文件存储位置,所有用户均可使用;使用 ls -ld /tmp 命令查询结果: 显示为 /tmp 为绿色 且权限属性最后一个为t
/usr:/usr Hierarchy,全局共享只读数据;(文件系统第二重要组成部分、第二分区)能独立分区
bin, sbin:可执行程序;
lib, lib64 :库文件;
include:C程序头文件;
share:平台的独立的共享数据文件;
local:第三方应用程序安装路径;
src:程序源代码;
/usr/local:第三方应用程序安装路径;可使用独立分区;
/var:可变数据存储位置;不能独立分区
cache:应用程序缓存数据;
lib:可变状态信息数据;
log:日志文件目录;
lock:锁文件;
run:进程相关的数据,主要用户存储pid文件;
/proc:基于内存的虚拟文件系统; 用于为内核及进程存储其相关信息; 它们多数为内核参数,例如net.ipv4.ip_forward,虚拟为/proc/sys/net/ipv4/ip_forward;以后系统调优多数为 调此目录下的文件参数值
/sys:sysfs虚拟文件系统,是一种提供了比/proc更为理想的访问内核数据的另一个途径;其主要作用在于为管理Linux系统上的设备提供一种统一模型的接口;
二、常用命令的使用
1.显示当前目录:pwd
pwd:printing working directory
echo $PWD :显示目录
echo $OLDPWD :显示父目录
[[email protected] ~]#cd /tmp[[email protected] /tmp]#pwd/tmp[[email protected] /tmp]#echo $PWD /tmp[[email protected] /tmp]#echo $OLDPWD/root
2.目录切换:cd
cd:change directory
用法:cd [/PATH/TO/SOMEDIR]
cd:切换回家目录;
注意:bash中,~表示用户的家目录;
cd ~:切换回家目录;
cd ~USERNAME:切换至指定用户的家目录;只有管理员才有的权限;
cd -:在上一次所在目录与当前目录之间来回切换;此命令比较有用。
[[email protected] ~]#cd /tmp[[email protected] /tmp]#pwd/tmp[[email protected] /tmp]#cd -/root
3.ls:list,列出指定目录下的内容,默认为当前目录
ls [OPTION]... [FILE]...
-a, --all:显示所有文件,包括.和..在内所有隐藏文件;
-A, --almost-all 列出目录中除了 “当前目录 .”和“父目录 ..”之外的所有文件,包括隐藏文件
-l:use a long listing format(按长列表输出格式显示)
-F,--classify : append indicator (one of */=>@|) to entries 给条目追加文件类型和标识符,区分文件和目录(*表示系统上可运行的文件)
-h, --human-readable:对数值做单位换算(K表示千字节,M表示兆字节,G表示吉字节);
-i: 显示每个文件的索引值(inode)
-d:查看目录自身的属性;
-R:recursive,递归显示;可显示目录及目录里面文件的内容
-r:reverse,降序显示;
--color={never|auto|always}:何时着色显示;
-s:输出每个文件的块大小;
-S: 按文件大小排序输出;
[[email protected] ~]#ls -l /roottotal 4-rw-r-xr-x 1 root root 0 Jul 30 10:50 1.sh-rw-------. 1 root root 2639 Jul 12 07:59 anaconda-ks.cfg
drwxr-xr-x:
d:文件类型,一个字符;
rwxr-xr-x:文件权限,permission;
perm:
r:readable
w:writable
x: excutable
权限三位一组:
左三位:属主的访问权限;
中三位:属组的所有用户的访问权限;
右三位:其它(other)用户的访问权限;
1:数字,表示文件被硬链接的次数;
root:一个用户名,表示当前文件的属主(owner);
root:一个组名,表示当前文件属组(group);
2639:一个数值,表示当前文件的size,默认单位为字节;可以跟 -h 选项一起使用
Jul 12 08:59 :一个时间,表示文件最近一次被修改的时间;
anaconda-ks.cfg:文件名;
4.显示文件或文件系统的状态:stat
stat - display file or file system status
语法格式:
stat [OPTION]... FILE...
文件的数据组成部分:
元数据(metadata):文件的元数据是指文件的属性 比如大小、权限、属主属组、时间戳等等;存放于文件系统中的inode;
数据(data):存放在数据块(data blocks)上;
注:任何一个磁盘格式化的时候都会把磁盘分为数据区和元数据区;而stat命令主要用于查看inode的相关信息的;
文件的三个时间戳:
最近访问时间(access time:atime),文件最近一次被访问的时间
最近修改时间(modify time:mtime),文件最近一次被修改的时间(数据)
最近改动时间(change time:ctime),文件最近一次改动的时间(元数据)
[[email protected] ~]#stat 1.sh File: ‘1.sh’ Size: 0 Blocks: 0 IO Block: 4096 regular empty fileDevice: 802h/2050dInode: 201368793 Links: 1Access: (0655/-rw-r-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2016-07-30 10:50:18.860790111 +0800Modify: 2016-07-30 10:50:18.860790111 +0800Change: 2016-07-30 10:51:01.820972642 +0800 Birth: -
5.touch命令
Update the access and modification times of each FILE to the current time
touch - change file timestamps
用法:
touch [OPTION]... FILE...
-t STAMP:指定时间格式:[[CC]YY]MMDDhhmm[.ss](手动指定时间,如果不指都表示当下时间)
如# touch -t 201606131434 b
-a:仅修改atime;
-m:仅修改mtime;
-c:不创建文件;
注:如果touch一个不存在的文件,则会创建一个空文件;
使用 # touch $(date +%F-%H-%M-%S) 命令:可以创建一个以当下时间为主的文件
[[email protected] ~]#touch `date +%F-%H-%M-%S`[[email protected] ~]#lltotal 4-rw-r-xr-x 1 root root 0 Jul 30 10:50 1.sh-rw-r--r-- 1 root root 0 Jul 30 11:03 2016-07-30-11-03-46-rw-------. 1 root root 2639 Jul 12 07:59 anaconda-ks.cfg
6.cp命令:copy
cp - copy files and directories
单源复制: cp [OPTION]... [-T] SOURCE DEST
多源复制: cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...
常用选项:
-i:交互式复制,即覆盖目标文件之前提醒用户确认;
-f:强制覆盖目标文件;
-R, -r, --recursive:递归复制目录及其内容;
-d:same as --no-dereference --preserve=links(保留链接本身的);
-P, --no-dereference:复制链接文件本身,而非默认的复制链接文件指向的源文件的内容(使用此选项复制链接类文件时相当于Windows上的快捷方式操作);
--preserve[=ATTR_LIST]:
指明保留的源文件属性列表:
默认为mode,ownership,timestamps;
额外:context(安全上下文), links(链接), xattr(扩展属性), all
-a, --archive:归档复制(创建备份的)
-dR --preserve=all
注意:仅管理员可保留属主和属组属性;
注:若-i和-f两个选项同时使用时,会提供交互式操作给用户提示
单源复制:cp [OPTION]... [-T] SOURCE DEST
如果DEST不存在(仅指基名所指定的文件不存在,路劲本身必须存在):则复制时先创建DEST文件,而后复制源文件的内容导入至目标文件;
如果DEST事先存在:
如果DEST是非目录文件:则覆盖目标文件;此操作极其危险,考虑到此centos定义 “cp=cp -i” 命令选项,提供交互式命令在复制时会有所提示;使用 \cp 可 以使用命令本身,不使用命令别名);
如果DEST目录:则在此目录中创建一个与原文件同名的文件,则导入其内容;
[[email protected] ~]#alias |grep cpalias cp=‘cp -i‘[[email protected] ~]#mkdir testdir[[email protected] ~]#cp 1.sh testdir/[[email protected] ~]#cp 1.sh testdir/cp: overwrite ‘testdir/1.sh’? y[[email protected] ~]#\cp 1.sh testdir/
多源复制:
基本前提:仅允许一种情形 DEST存在,且必须是目录;否则即为错误;
[[email protected] ~]#cp 1.sh anaconda-ks.cfg testdir/cp: overwrite ‘testdir/1.sh’? y[[email protected] ~]#ls testdir/1.sh anaconda-ks.cfg[[email protected] ~]#cp 1.sh anaconda-ks.cfg nodircp: target ‘nodir’ is not a directory
7.mv命令
Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY. Mandatory arguments to long options are mandatory for short options too.
mv - move (rename) files
mv [OPTION]... [-T] SOURCE DEST
mv [OPTION]... SOURCE... DIRECTORY
mv [OPTION]... -t DIRECTORY SOURCE...
常用选项:
-i, --interactive:使用交互式选项操作
-f, --force do not prompt before overwriting
注意:源文件目录与目标文件目录相同时,为rename机制;否则即为move。
无论移动的源文件是文件还是目录都不需要使用-R选项
8.rm命令
rm - remove files or directories
rm [OPTION]... FILE...
常用选项:
-i, --interactive
-f, --force
-r, -R, --recursive:递归删除目录及其内容(和cp命令一样,删除目录时需要使用此选项);
注意:Linux没有回收站功能,所以不要随意执行 “rm -rf /”或“rm -rf /*” 命令!
三、bash的特性之glob
glob:文件名通配;快速引用多个文件;文件名整体匹配度检测;
元字符:基于元字符可编写匹配模式(pattern);
*:匹配任意长度的任意字符;
?:匹配任意单个字符;
[ ]:匹配指定集合内的任意单个字符;
[a-z], [A-Z]:不区分字符大小写;
[0-9] :0-9之间的任意单个数字
[a-z0-9]:既有字母又有数字的集合
字符集合表示:
[[:upper:]]:所有大写字母;
[[:lower:]]:所有小写字母;
[[:digit:]]:所有的数字;
[[:alpha:]]:所有字母;
[[:alnum:]]:所有字母和数字;
[[:space:]]:空白字符;
[[:punct:]]:标点符号(punctuation);
[^ ]:匹配指定集合外的任意单个字符;
[^[:alpha:]]:所有的非字母集合
三、软连接和硬链接
1.Linux链接概念
Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。默认情况下,ln命令产生硬链接。
2.硬连接
硬连接指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(Inode Index)。在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,因为对应该目录的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。
3.软连接
另外一种连接称之为符号连接(Symbolic Link),也叫软连接。软链接文件有类似于Windows的快捷方式。它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
4.通过实验加深理解
[[email protected]]$ touch f1 #创建一个测试文件f1[[email protected]]$ ln f1 f2 #创建f1的一个硬连接文件f2[[email protected]]$ ln -s f1 f3 #创建f1的一个符号连接文件f3[[email protected]]$ ls -li # -i参数显示文件的inode节点信息total 4201364821 -rw-------. 1 root root 2639 Jul 12 07:59 anaconda-ks.cfg201368793 -rw-r--r-- 2 root root 0 Jul 30 11:31 f1201368793 -rw-r--r-- 2 root root 0 Jul 30 11:31 f2201364836 lrwxrwxrwx 1 root root 2 Jul 30 11:32 f3 -> f1
从上面的结果中可以看出,硬连接文件f2与原文件f1的inode节点相同,均为201368793,然而符号连接文件的inode节点不同。
[[email protected]]$ echo "I am f1 file" >>f1[[email protected]]$ cat f1I am f1 file[[email protected]]$ cat f2I am f1 file[[email protected]]$ cat f3I am f1 file[[email protected]]$ rm -f f1[[email protected]]$ cat f2I am f1 file[[email protected]]$ cat f3cat: f3: No such file or directory
通过上面的测试可以看出:当删除原始文件f1后,硬连接f2不受影响,但是符号连接f1文件无效
5.总结
依此您可以做一些相关的测试,可以得到以下全部结论:
1).删除符号连接f3,对f1,f2无影响;
2).删除硬连接f2,对f1,f3也无影响;
3).删除原文件f1,对硬连接f2没有影响,导致符号连接f3失效;
4).同时删除原文件f1,硬连接f2,整个文件会真正的被删除。