第9章 Linux文件核心属性知识
9.1 回顾Linux文件属性知识
前文已经讲解过,Linux系统中的文件或目录的属性主要包括:索引节点(Inode)、文件类型、权限属性、链接数、所归属的用户和用户组、最近的修改时间等内容,更多内容请读者回顾第8章,此处不再赘述。
本章将为大家讲解剩余文件属性的含义,以及相关的重要Linux基础知识。
9.2 用户及用户组
用户和用户组是Linux系统中很重要的知识,本节将介绍Linux相关的基础知识,后文会进行更详细的讲解。用户和用户组的属性对应于命令ls-lhi/data结果中的第4列和第5列,示例如下:
139170 -rw-r--r--. 1 root root 22 Mar 11 15:17 oldboy.txt
说明:
命令中带有不同颜色底纹的root字符串的第4列表示用户(也叫属主)列,第5列表示用户组列。
9.2.1 Linux多用户多任务介绍
Linux是一个多用户、多任务的操作系统,在讲解Linux用户及用户组之前,我们先来简单了解下多用户、多任务操作系统的概念。
1.Linux单用户多任务
鉴于大家对Windows系统比较熟悉,因此这里先以Windows系统为例进行阐述。假设我们在以管理员账号administrator登录Windows系统之后,需要编辑word文档里的内容,但是在编辑文件的过程中,又想打开音乐播放器听音乐;同时还打开了微信或QQ。那么这其中编辑word文档、打开播放器、登录微信或QQ,这些操作每种都是一项任务。因此,在以上过程中我们同时执行了若干个任务,也就是说,一个administrator用户,为了完成工作和相关的任务,同时执行了若干个服务或进程。事实上,Linux也是这样的一个操作系统,当你登录后,你也可以同时开启很多的服务任务和进程,而各个服务都会运行得很好,且对其他任务没有任何影响,这种一个用户登录系统执行多个服务任务和进程的情况,就称为单用户多任务。
2.Linux多用户多任务
有时可能是很多用户同时使用同一个系统,如笔者所在公司的机器,每台机器都可以被若干个运维人员登录部署或解决相关的故障问题,但并不是所有的运维人员都要做同一件事情,所以这就存在多用户、多任务的情况。
举个例子,比如oldboyedu.com服务器,上面有系统管理员root用户、Apache用户、常规普通用户等。在同一时刻,可能有的人正在上传软件包部署Apache服务;有的正在查看服务器日志,有的人正在登录编写Shell程序;不同的维护人员对系统的维护或查看,所用的账号既可以是不同的普通账号,也可以是超级账号root;不同用户所具有的权限也不同,不同的任务由不同的维护人员来完成,也可以说是不同的用户。
值得注意的是,多用户、多任务并不是指大家同时挤到一台机器的键盘和显示器前来操作机器,多用户可能是通过SSH客户端工具等远程登录到服务器上来进行的,比如对服务器的远程控制,只要具有相关用户的权限,任何人都可以访问服务器。
9.2.2 用户(user)介绍
通过前文的讲述,相信大家已经知道,Linux是一个多用户、多任务的分时操作系统。如果要使用系统资源,就必须向系统管理员申请一个账户,然后通过这个账户进入系统。这个账户和用户是同一个概念,可以通过建立不同属性的用户来实现不同的作用或权限,一方面,可以合理地利用和控制系统资源,另一方面也可以帮助用户组织文件,提供对用户文件的安全性保护。
每个用户都拥有一个唯一的用户名和用户口令,在登录系统时,只有正确输入了用户名和密码,才能登入系统和相应的目录(除了密码验证之外,还可以是密钥验证)。
在生产环境中,我们一般会为每个有权限管理服务器的运维人员分配一个独立的普通用户账号及8位(包含数字、字母、特殊字符)以上的密码,如oldboy。该人员只能通过这个账号登录到系统中进行维护,当需要超级用户权限时,可以通过“sudo命令名”的方式来执行仅root用户才允许执行的权限。当然,sudo权限要尽量地小。此外,当运维人数不多时(如两三个),也可以直接通过su-命令切换到超级用户root下执行相应的维护工作。在这里需要特别提醒大家注意的是,维护时,如果不需要root权限,就不要进入root用户下操作,以减少误操作对系统带来的故障风险,请读者切记。
提示:sudo和su是两个重要的切换用户角色的命令,后文会详细讲解。
9.2.3 Linux系统中用户角色的划分
在Linux系统中用户是分角色的,由于用户角色不同,权限和所完成的任务也不同;值得注意的是,对于Linux系统来说,用户的角色是通过UID和GID来识别的。
特别是UID,在Linux系统运维工作中,一个UID可以唯一标识一个系统用户的账号(相当于我们的身份证)。用户系统账号的名称(如oldboy)其实是给人(管理员)看的,Linux系统能够识别的仅仅是UID和GID这样的数字。
·UID(User Identify):用户ID,相当于各位的身份证,在系统中是唯一的。
·GID(Group Identify):组ID,相当于各位的家庭住址或者你们的学校ID,户口本的“号码”等。
1.超级用户:root(皇帝)
若将root比喻为皇帝,那么root的家目录就是皇宫,操作系统就是整个国家。
默认是root用户,它的UID和GID均为0。root用户在每台Unix/Linux操作系统中都是唯一且真实存在的,通过它可以登录系统,可以操作系统中的任何文件和命令,拥有最高的管理权限。
在生产环境中,一般会禁止root账号通过SSH远程连接服务器(保护好皇帝),当然了,也会更改默认的SSH端口(保护好皇宫),以加强系统安全。
在企业工作中,如果没有特殊需求,应该尽量在普通用户下操作任务,而不是在root账户下。
在Linux系统中,UID为0的用户就是超级用户。但是通常不会将用户的UID改为0,而是通过sudo命令管理提权,可以细分到每个命令的权限分配。
2.普通用户(老百姓)
这类用户一般是由具备系统管理员root权限的运维或系统管理人员添加的。例如,oldboy这类用户可以登录系统,但仅具备操作自己家目录中的文件及目录的权限,除此之外,还可以进入或浏览相关目录(如/etc、/var/log),但是无法创建、修改和删除任何文件。
普通用户可比喻成皇帝的臣民/贫民,别干坏事,国家有法律管束你。若为普通用户授权权限(sudo),就相当于为臣民封官。
普通用户可通过命令su-或su-root切换到root用户角色,这种切换类似于农民起义,推翻了皇帝,自己当皇帝。
sudo ls命令表示授权相关用户在执行ls命令时,具有sudo配置的权限,一般是在执行ls命令的过程中才具有root用户的权限,可将sudo理解为尚方宝剑,可通过它为皇帝办事,有一定的权限,但还是自己。
3.虚拟用户(傀儡)
要将虚假用户与真实的普通用户区分开来,这类用户最大的特点是安装系统后会默认存在,且默认情况下大多数不能登录系统,但是,它们是系统正常运行不可缺少的,它们的存在主要是为了方便系统管理,满足相应的系统进程对文件属主的要求。例如,系统默认的bin、adm、nobody、mail用户等。由于服务器业务角色的不同,一部分用不到的系统服务会被禁止开机执行,因此,在做系统安全优化时,被禁止开机启动了的服务所对应的虚拟用户也可以处理掉(删除或注释)。
Linux安全优化注意事项
·安装系统后可以删除用不到的虚拟用户,但最好不要删除而是注释掉,万一出现问题还可以恢复回来。
·在部署服务的时候,一般需要创建虚拟用户,满足服务启动的属主需求!例如,在部署Apache、Nginx、MySQL、NFS、Rsync、Zabbix、Redis等服务时就需要预先创建好对应的虚拟用户,然后再部署服务。
9.2.4 Linux系统中不同用户角色对应的UID说明
下面的表9-1针对Linux用户进行了分类说明。
表9-1 有关Linux用户的分类说明
9.2.5 多用户操作系统的安全
从实际应用来看,多用户系统使得系统管理变得更为方便了;从安全角度来说,多用户系统也更为安全,比如普通用户oldboy下的某个文件不想让其他用户看到,只需设置一下该文件的权限为只有普通用户oldboy一个用户可读可写可编辑(后文会详细讲解权限相关的内容)就行了,这样一来就只有普通用户oldboy一个用户可以对其私有文件进行操作,从而保护了每个用户私有数据的安全性。
9.2.6 用户组(group)介绍
简单地说,Linux系统中的用户组(group)就是具有相同特征的用户(user)集合;为了便于大家理解,这里打个比方:一个公司、一个家庭就是一个集合,类似于这里的用户组,公司的员工和家庭中的成员就相当于这里的用户。
有时我们需要让多个用户具有相同的权限,比如查看、修改某一文件或目录,如果不用用户组,那么这种需求在授权时就会很难实现。有了用户组就方便多了,只需要将授权的用户都加入到同一用户组里,然后修改与该文件或目录对应的用户组的权限,即让用户组具有符合需求的操作权限即可。这样用户组下的所有用户对该文件或目录就会具有相同的权限,这就是用户组的用途。
将用户分组是Linux系统(Windows中也是一样的)中对用户进行管理及控制访问权限的一种手段,定义用户组,可以在很大程度上简化运维管理的工作。
实际上,在日常生活中,对人类的分组也是无处不在的,大到国家,小到公司、家庭、学校、班级等都是类似于Linux中用户组的概念,而其中的成员就类似于Linux用户组中用户的概念。
用户和用户组的对应关系有:一对一、一对多、多对一和多对多。为了方便大家理解,下面通过图9-1更形象地来展示这种关系。
图9-1 用户与用户组关系
用户和用户组的对应关系具体说明如下。
·一对一:即一个用户可以存在一个组中,也可以是组中的唯一成员(如,root)。
·一对多:即一个用户可以存在于多个用户组中。比如,图9-1中普通用户oldboy可以是sa组成员,也可以是Java用户组成员,还可以是tech用户组成员,这里的oldboy用户具有sa、Java、tech等多个组的共同权限。
·多对一:多个用户可以存在于一个组中,这些用户具有与组相同的权限,这条已在上文中讲解过。
·多对多:多个用户可以存在于多个组中,并且几个用户可以归属于相同的组。其实多对多的关系是前面三条的扩展,理解了上面的三条,这条也就好理解了。
9.2.7 创建用户及用户组命令
要想创建Linux用户,就需要用到useradd命令,具体操作如下:
[root@oldboy ~]# useradd oldboy #<==添加用户oldboy,会默认创建一个oldboy用户组,人必须属于家庭,所以用户创建也必须要属于一个组,默认就属于与用户同名的组。 [root@oldboy ~]# id oldboy #<==查看oldboy用户、组及ID信息。 uid=500(oldboy) gid=500(oldboy) groups=500(oldboy) [root@oldboy ~]# groupadd sa #<==添加sa用户组,用户组可以单独存在,而没有用户属于组。 [root@oldboy ~]# su - oldboy #<==从root用户切换到oldboy用户下。 [oldboy@oldboy ~]$ touch test.txt #<==创建文件,注意提示符变成了$。 [oldboy@oldboy ~]$ mkdir inca #<==创建目录。 [oldboy@oldboy ~]$ ls -l total 4 drwxrwxr-x. 2 oldboy oldboy 4096 Mar 13 06:13 inca #<==目录默认属于创建它的用户和组。 -rw-rw-r--. 1 oldboy oldboy 0 Mar 13 06:13 test.txt #<==文件默认属于创建它的用户和组。 #<==文件生成一定是由用户创建的,因此文件一生成也必须要属于一个用户及组,默认就是属于创建它的用户的和组。
更多有关用户及用户组的知识,请阅读后文的相关章节。
9.3 文件的权限列
文件的权限是Linux系统极其重要的知识,本节将介绍相关的基本知识,后文还会有更详细的讲解。文件的权限列属性对应于命令ls-lhi/data结果中第2列中间的9位字符串,示例代码如下:
139170 -rw-r--r--. 1 root root 22 Mar 11 15:17 oldboy.txt
对于文件权限列的说明具体如下。
1)代码中带有不同颜色底纹的rw-r--r--字符串就表示文件对应的访问权限。
2)第二列权限的结尾多了个点号,大家看到了吗?当系统的SeLinux功能开启时,这个地方就会多一个点号,这个点号是与SeLinux(企业里大多会将Selinux功能停止掉)相关联的,没有什么实际用途,有关点号的作用仅在此提及,其他地方不再赘述。
文件权限说明
在Linux中,文件或目录的权限与用户及用户组的关联很大,要理解这部分内容,需要先了解一下Linux系统中用户管理方面的知识。前文已经详细讲解过这部分内容,更多用户管理文档的细节请参考后面的章节。
在Linux中,每个文件或目录都有一组共9个基础权限位,每三位字符分为一组,它们分别是属主(也称用户)权限位(占开头的前三个字符,如rw-)、用户组权限位(占中间的三个字符,如r--)、其他用户权限位(占结尾的三个字符,如r--)。最终形式如“rw-r--r--”。Linux正是通过这9个权限(更多权限位后面会提到)位来控制文件用户(或称属主,即Owner/User)、用户组(或称属组,即Group)以及其他用户(Other)对文件的访问权限的,不同组的权限位说明如图9-2所示。
图9-2 9位权限位对应功能说明
不同权限位对应的用户和组权限控制的详细图解如图9-3所示。
图9-3 不同权限位对应的用户和组权限控制的具体图解
其中,表示权限的字符r、w、x、“-”分别代表了特定的含义,具体说明如下。
·r(read):可读权限,对应数字4。
·w(write):可写权限,对应数字2。
·x(Execute):可执行权限,对应数字1。
·没有任何权限,对应数字0。
后文还会提到一些特殊的权限位t、T、s、S、X、x、“+”,暂且忽略不表。
在图9-3中,oldboyfile所属的用户为root,即root用户对oldboyfile文件的访问权限对应于前3个字符。因为这里的前3个字符为rwx,所以root用户对oldboyfile有读、写和执行的权限。
而oldboyfile所属的用户组为root,即root用户组内的成员对oldboyfile文件的访问权限对应于中间3个字符。因为这里中间的3个字符为r-x,所以root用户组的任意成员对oldboyfile有读和执行的权限,但没有写的权限。
同理,非root用户和root用户组的成员对oldboyfile文件的访问权限对应于最后3个字符。因为这里的最后3个字符为r-x,所以其他用户和组对oldboyfile有读和执行的权限,没有写的权限。
有关文件权限的更多内容,请参见后面章节的详解。
9.4 文件的修改时间属性列
文件的时间戳是Linux系统中不太重要的知识,读者了解即可。文件的最后修改时间列属性对应于命令ls-lhi/data结果中的第7~9列,示例代码如下:
139170-rw-r--r--. 1 root root 22 Mar 11 15:17 oldboy.txt
说明:
代码中带有不同颜色底纹的Mar 11 15:17字符串就表示文件对应的最后修改时间。
文件的时间戳属性具体包含3种类型,即访问时间(access)、修改时间(modify)、改变时间(change),详细描述如下:
Access: 2017-07-30 17:48:20.502156890 +0800 #<==文件最后被访问的时间。 Modify: 2017-07-30 17:48:45.006106223 +0800 #<==文件最后被修改的时间。 Change: 2017-07-30 17:48:45.006106223 +0800 #<==文件状态最后被改变的时间。
对应ls命令,查看上述时间戳的选项,详细描述如下:
mtime: 最后修改时间(ls -lt) #<==修改文件内容,文件的修改时间(modify time)会改变。 ctime: 状态改变时间(ls -lc) #<==修改文件内容、移动文件或改变文件属性等,文件的change时间会改变。
当执行ls-l命令时,显示的是文件的最后修改时间,有关更改时间戳的知识,可以参考前文的touch、ls命令章节。
9.5 索引节点
索引节点(Inode)是Linux系统中重要的基础知识,这部分知识内容比较复杂,不易理解,因为其中会涉及Linux文件系统的核心知识,在这里读者尽力理解就行了,实在理解不了,等阅读了磁盘和文件系统的相关章节后再回头来看,相信那时再来理解就简单了。
索引节点Inode列的属性对应于“ls-lhi/data”命令结果中第1列的一串数字,示例代码如下:
139170 -rw-r--r--. 1 root root 22 Mar 11 15:17 oldboy.txt
上面代码中带底纹的139170这串数字就表示文件对应的索引节点,这里所提的文件也包含目录,广义地讲,Linux里一切皆文件,针对文件的说明几乎同样都适用于目录。
9.5.1 Linux磁盘存储数据的经典描述
一块磁盘从放入计算机到被Linux系统识别,再到最终可以存储数据是需要一系列处理过程的,具体过程如下。
1)磁盘要存储数据,就相当于盖房子住人。
2)磁盘要分区才能存储数据,相当于盖房后,要打隔断分出卧室、厨房、卫生间等区域。
3)磁盘分区完成后,还要进行格式化,创建文件系统才能存储数据,相当于房子打完隔断后还得装修(不同的装修的风格相当于不同的文件系统)。
4)磁盘分完区格式化后还必须要挂载到指定的目录(即挂载点)下才能存放数据,这相当于为房子安装门和窗户,最终人才能进出、与外界通信以及居住。
希望通过这个比喻,读者对磁盘的使用过程有了一个基本的了解。
9.5.2 什么是索引节点
索引节点(Index node,Inode)在每个Linux存储设备(磁盘或硬盘)或存储设备的分区(此时的存储设备可以是硬盘、软盘、U盘,等等)中被格式化为ext系列文件系统之后,都会生成两部分内容:第一部分是Inode(默认大小为128或256字节),第二部分是Block(默认大小为1~4KB)。由于磁盘或分区一般都比较大,因此,Inode和Block都会存在很多个,并且都可以存放数据信息。
Inode本质上是一小块具备唯一数字编号的存储空间,主要用来存放文件(目录)属性(例如ls-l的结果)的数据信息,注意,Inode里面唯独不包含文件名本身(文件名不算文件的属性)。
Block称为磁盘块,是用来存放实际数据的实体单元(ext文件系统一般最大为4KB),即用来存放真正的数据,例如,照片、视频等普通文件数据,单个的大文件需要占用多个Block块来存储,特别小的单个文件如果不能占满整个Block块,那么剩余的空间也无法再利用。
Inode存储的属性信息(即ls-l的结果),包括但不限于文件大小、属主(用户)、归属的用户组、文件权限、文件类型,“修改”时间等,还包含指向文件的实体指针等(Block的位置,即Inode节点与Block的对应关系)。
9.5.3 查看文件内容与Inode和Block的关系
Inode除了要记录文件属性的信息之外,还会为每个文件进行信息索引,所以就有了Inode的数值。操作系统根据指令,即可通过Inode的值最快速地找到相对应的文件实体。文件、Inode和Block之间的关系见图9-4。
图9-4 查看文件内容与Inode和Block的关系
老男孩教育的教室门口贴了一张纸(相当于Inode),纸上标有大家的名字和座位信息,这些信息就相当于是文件的属性信息。学生的座位就相当于是Block(实际文件的实体),如图9-5所示。
图9-5 老男孩教育教室门口学员信息
无论是班主任、导师、讲师,还是其他人,如果想找学生,只要看这张表,就可以快速定位到具体的位置并找到对应的学员,Linux系统查找数据就是根据这样的方法,只不过这张表对应的就是Inode,座位对应的就是磁盘的Block。
再打个比方,比如一本书,存储设备或分区就相当于这本书(如图9-6所示),Block相当于书中的每一页内容,而Inode就相当于这本书前面的目录,一本书包含了很多内容,一个知识点可能有多页,如果想查找某部分或某知识点的内容,我们一般会先查看书的目录,通过目录我们能够更快地找到想要查看的知识点相关内容。虽然这样类比不太恰当,但还算是比较形象。
图9-6 Inode与Block的关系
当我们使用ls命令查看某个目录或文件时,如果加上-i参数,就可以看到Inode节点了;根据前面所讲的例子,使用的命令ls-li中若带有-i参数,即可查看文件的Inode数值,示例代码如下:
[root@oldboy ~]# ls -li /etc/hosts 130078 -rw-r--r--. 2 root root 208 Mar 11 00:21 /etc/hosts
提示:也可以使用stat查看文件属性,以及相应的Inode数值。
9.5.4 Inode和Block的特点
1.Inode的特点
总体来说,Inode具有如下一些特点。
·ext3/ext4文件系统(CentOS 5.x/6.x默认的文件系统)下,一个非空文件至少要占用一个Inode(有且只有一个)和一个Block(可以有多个)。
·Inode节点号相同的文件,互为硬链接文件,可以认为是一个文件的不同入口。
·Inode在某一个文件系统(分区)内是唯一的。
2.Block的特点
Block的特点具体如下。
·磁盘读取数据是以Block为单位进行读取的。
·每读取一个Block就会消耗一次磁盘I/O(input/output,磁盘读写)。
·若文件比较大,那么一个文件可能占用多个Block。
·若文件比较小,那么一个Block的剩余空间会被浪费,无论内容有多小。
9.5.5 查看和管理Inode
查看文件系统Inode总量以及剩余量的命令如下:
[root@oldboy /]# df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda3 479552 56299 423253 12% / tmpfs 127032 1 127031 1% /dev/shm /dev/sda1 51200 38 51162 1% /boot
查看磁盘的使用量相当于是查看Block的情况,示例命令如下:
[root@oldboy data]# df –h #Block是存放数据的位置,数据实体 Filesystem Size Used Avail Use% Mounted on /dev/sda3 9.2G 1.6G 7.2G 19% / tmpfs 937M 0 937M 0% /dev/shm /dev/sda1 194M 34M 151M 19% /boot /dev/sdb 99M 5.6M 89M 6% /mnt
通过“ls-i”或者“stat文件名”命令可以查看文件的Inode数值。
通过dumpe2fs/dev/sda1命令可以查看分区的Inode和Block的单位大小及各种相关信息。
9.5.6 磁盘空间不足导致企业故障的案例
在了解了磁盘的Inode和Block之后,我们就能够明白磁盘满了分两种情况:一种是Inode数量耗尽了,另一种则是Block满了。
Block耗尽的情况基本上大家都能理解,500GB硬盘存放600GB的大片,将直接耗尽所有的Block。但是Inode耗尽的情况,一般的运维人员可能就会搞不清楚了,因为每创建一个文件都会占用一个Inode,所以当文件无限多并且足够小的时候,Inode就会先于Block耗尽,导致看起来磁盘空间充足,但是却会收到提示“磁盘空间不够”的情况。
以下是磁盘装满的两种企业模拟案例。
环境准备,命令集合如下:
mkdir -p /app/logs #<==创建用于挂载的目录。 dd if=/dev/zero of=/dev/sdc bs=8K count=10 #<==创建指定大小的文件。 mkfs.ext4 /dev/sdc #<==格式化。 mount -o loop /dev/sdc /app/logs #<==挂载。 df -h #<==检查挂载结果。
1.模拟Block被占满了的测试案例
[root@oldboy ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 8.8G 1.7G 6.8G 20% / tmpfs 931M 0 931M 0% /dev/shm /dev/sda1 190M 40M 141M 22% /boot /dev/sdc 73K 14K 55K 21% /app/logs #<==磁盘使用正常(Block)。 [root@oldboy ~]# cd /app/logs/ [root@oldboy logs]# ls -lh /bin/ls -rwxr-xr-x. 1 root root 115K Mar 23 2017 /bin/ls [root@oldboy logs]# cp /bin/ls . #<==把大文件复制到这个磁盘分区中。 cp: writing `./ls': No space left on device #<==报错了,因为磁盘空间不够了。 [root@oldboy logs]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 8.8G 1.7G 6.8G 20% / tmpfs 931M 0 931M 0% /dev/shm /dev/sda1 190M 40M 141M 22% /boot /dev/sdc 73K 70K 0 100% /app/logs #<==磁盘已满,这时Block用光了。 [root@oldboy logs]# mv ls /tmp/ #<==解决方法就是删除对应的文件,这里选择 移动到/tmp中。 [root@oldboy logs]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 8.8G 1.7G 6.8G 20% / tmpfs 931M 0 931M 0% /dev/shm /dev/sda1 190M 40M 141M 22% /boot /dev/sdc 73K 14K 55K 21% /app/logs #<==磁盘空间恢复了。
2.模拟Inode耗尽的测试案例
[root@oldboy logs]# touch {1..6}.txt touch: cannot touch `6.txt': No space left on device #<==创建文件的时候,提示 磁盘空间不足。 [root@oldboy logs]# touch 7.txt touch: cannot touch `7.txt': No space left on device #<==创建文件的时候,提示 磁盘空间不足。 [root@oldboy logs]# df -h #<==查看磁盘空间的使用情 况(Block)。 Filesystem Size Used Avail Use% Mounted on /dev/sda3 8.8G 1.7G 6.8G 20% / tmpfs 931M 0 931M 0% /dev/shm /dev/sda1 190M 40M 141M 22% /boot /dev/sdc 73K 14K 55K 21% /app/logs #<==还有剩余,这里指的是 Block还有剩余。 [root@oldboy logs]# df -i #<==查看磁盘空间的使用情 况(Inode)。 Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda3 593344 59648 533696 11% / tmpfs 238282 1 238281 1% /dev/shm /dev/sda1 51200 40 51160 1% /boot /dev/sdc 16 16 0 100% /app/logs #<==但是Inode已经用光了, 所以会提示磁盘空间不足。 [root@oldboy logs]# mv *.txt /tmp #<==删除对应的小文件,这里移 动到/tmp中。 [root@oldboy logs]# df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda3 593344 59446 533898 11% / tmpfs 125596 1 125595 1% /dev/shm /dev/sda1 51200 38 51162 1% /boot /dev/sdc 16 10 0 62% /app/logs #<==故障解决,Inode还有剩 余空间。 [root@oldboy logs]# touch 7.txt #<==创建文件将不再报错了。
3.磁盘空间满了故障情况总结
情况一:Block耗尽的情况,例如500GB磁盘存放400GB+200GB的视频。
情况二:Inode耗尽的情况,产生大量的小文件(小于1KB)。
4.出现No space left on device问题的企业案例
如果向磁盘写入数据则会提示如下错误:No space left on device(磁盘空间不足),可通过df-h命令查看磁盘空间,若此时发现没满,请问可能的原因是什么?企业场景在什么情况下会导致这个问题发生?
解答:还是因为Inode耗尽了,多数情况下是基于日常Linux定时任务crond配置不当导致的,具体案例和解决方案请参见Linux定时任务章节。
9.6 硬链接及软链接数知识
软硬链接的概念是Linux系统中重要的基础知识之一,需要读者熟练掌握,本节会带领大家了解软硬链接的知识。硬链接数属性对应于前文“ls-lhi/data”命令结果中的第3列(数字),示例代码如下:
139170 -rw-r--r--. 1 root root 22 Mar 11 15:17 oldboy.txt
说明:
上述代码段中带底纹的1这样的数字列就表示文件(目录)对应的硬链接数。
9.6.1 链接的概念
在Linux系统中,链接可分为两种:一种为硬链接(Hard Link),另一种为软链接(Soft link)或符号链接(Symbolic Link)。前面讲解过,ln命令就是用来创建链接文件的,在默认不带任何参数的情况下,执行ln命令创建的链接是硬链接。
如果是使用ln-s创建的链接,则为软链接,软链接文件的文件类型为l(字母L的小写)。
创建硬链接的语法:“ln原始文件目标文件”(注意空格)。
创建软链接的语法:“ln-s原始文件目标文件”(目标文件不能事先存在)。
9.6.2 硬链接知识与实践
硬链接是指通过索引节点(Inode)进行的链接。在CentOS6及以前的Linux(ext2、ext3、ext4)默认文件系统中,存在于在磁盘分区中的文件不管是什么类型都会为它分配一个唯一的编号,这个编号就称为索引节点编号(Index Inode),简称Inode,各个文件对应的这个索引节点编号就类似于我们生活中的身份证号码,在Linux同一文件系统中该编号是唯一的。
在Linux系统中,多个文件名指向同一个索引节点(Inode号相同)(Inode)是正常且被允许的。这种情况下的两个文件就称作互为硬链接文件,本质上就是相同文件的两个名字(类似真名和网名一样,都表示一个人)。在同一个分区/文件系统中,Inode号码相同的文件一定是硬链接文件。
硬链接文件就相当于是原始文件的另外一个访问入口。硬链接的作用之一是允许一个文件拥有多个有效的文件名(多个访问入口,类似于超市的多个入口),这样用户就可以建立硬链接到重要的文件上,为避免“误删”源数据加一份保险(很多硬件存储的快照功能就应用了这个原理,增加一个快照就多了一个硬链接,多了一个硬链接就会增加一层数据的安全)。
因为文件系统(ext)的原理是,只要文件的索引节点(Inode Index)还有一个以上的硬链接,那么,只删除其中的一个硬链接(即仅仅删除了该文件的链接指向)并不会影响索引节点本身和其他的链接(即数据文件实体并未被删除),只有在文件的最后一个硬链接被删除之后,此时如果有新数据要存储到硬盘上,或者系统通过类似的fsck做磁盘检查的时候,被删除文件的数据块及目录的链接才会被释放,空间将被新数据占用并覆盖。当然,这样一来,数据就再也无法找回了。
也就是说,在Linux系统中,删除静态文件(没有进程调用的文件)的条件是与之相关的所有硬链接文件均被删除(暂时这样理解即可,后文会进一步介绍其与进程的占用也有关)。一个静态文件被彻底删除的条件就是该文件的硬链接数量为零。
下面给出一个文件的多个硬链接的形象图以帮助大家理解,图9-7即为硬链接原理图。
图9-7 文件硬链接原理图
根据硬链接示意图可以知道,当删除oldboyfile和oldboyfile_hard_link两者任意之一时,只相当于删除了该文件到Inode之间的连接,通过未删除的文件名依然可以访问到文件实体。
硬链接的创建方法为直接执行命令“ln源文件目标文件(硬链接文件)”,具体实例演示代码如下:
[root@oldboy ~]# echo "I am oldboy" >oldboyfile #<==创建源文件。 [root@oldboy ~]# cat oldboyfile #<==查看。 I am oldboy [root@oldboy ~]# ln oldboyfile oldboyfile_hard_link #<==创建硬链接。 [root@oldboy ~]# cat oldboyfile_hard_link #<==查看硬链接,内容与源文件相同。 I am oldboy [root@oldboy ~]# ls -li oldboyfile oldboyfile_hard_link #<==查看索引节点。 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile #<==索引节点是相同的,链接 数为2。 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile_hard_link #<==索引节点是相同的。 [root@oldboy ~]# rm -f oldboyfile #<==删除源文件。 [root@oldboy ~]# ls -li oldboyfile oldboyfile_hard_link ls: cannot access oldboyfile: No such file or directory #<==源文件已删。 400789 -rw-r--r--. 1 root root 12 Mar 13 09:23 oldboyfile_hard_link #<==链接数变为1。 [root@oldboy ~]# cat oldboyfile_hard_link #<==内容依然存在,数据应该没有丢失。 I am oldboy [root@oldboy ~]# ln oldboyfile_hard_link oldboyfile #<==反过来创建硬链接。 [root@oldboy ~]# ls -li oldboyfile oldboyfile_hard_link 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile #<==又回来了,链接数又都 为2了。 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile_hard_link [root@oldboy ~]# cat oldboyfile #<==文件回来了,内容也有了。 I am oldboy
硬链接知识小结
·具有相同Inode节点号的多个文件互为硬链接文件,本质上是相同文件的不同文件名。
·删除硬链接文件或者删除源文件任意之一,文件实体并未被删除。
·只有删除了源文件及与源文件对应的所有硬链接文件,文件实体才会被删除。
·待所有的硬链接文件及源文件均被删除之后,再存放新的数据时,新数据会占用这个文件的空间。磁盘进行fsck检查的时候,删除的数据就会被系统回收(养成删除及使用多套环境测试的好习惯)。
·硬链接文件就是文件的另一个入口(相当于超市的前门、后门)。
·可以通过对文件设置硬链接文件,来防止重要文件被误删。
·通过执行命令“ln源文件硬链接文件”,即可完成硬链接的创建。
·硬链接文件是普通文件,因此可以使用rm命令删除。
·对于静态文件(没有进程正在调用的文件)来讲,当对应的硬链接数为0(i_link)时,文件就被删除。i_link的查看方法是执行ls-lhi,然后查看结果的第三列。
·创建硬链接只能针对文件,不能针对目录。
9.6.3 软链接知识与实践
软链接(Soft Link)也称为符号链接(Symbolic Link,symlink)。Linux里的软链接文件就类似于Windows系统中的快捷方式。软链接文件实际上是一个特殊的文件,文件类型用字母l表示。可以将它理解为一个文本文件,这个文件中包含有软链接,其指向的是另一源文件的位置信息内容,因此,通过访问这个“快捷方式”就可以迅速定位到软链接所指向的源文件实体。
软链接的创建方法为:执行命令“ln-s源文件软链接文件”。
要想创建软链接,那么目标文件将是不能存在的,这个文件是要用ln命令创建的,创建软链接必须要有源文件,即针对哪个文件做软链接。
软链接文件的基本示意图如图9-8所示。
在图9-8中,软链接文件通过自身的Inode(存放原始文件路径信息,而不是读Block),读到了软链接信息,并指向了原始文件,进而读到原始文件名,以及原始文件的Inode,再通过原始文件的Inode读到原始文件的内容(Block),这就是访问软链接文件来读取数据的原理。
早期的软链接是读取自己的Block以获取原始文件的路径名信息,但是这样的访问方式效率很低,对于Linux(POSIX系统)系统来说,还有一种更好的方法,称为fast symlinks,原理就是软链接的Block不存放源文件位置了,而是直接将源文件位置存放在Inode里面,既省事又更快捷[1]。
图9-8 软链接文件的示意图
1.文件的软链接示例
文件的软链接示例代码如下:
[root@oldboy ~]# ls -li oldboyfile oldboyfile_hard_link 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile_hard_link [root@oldboy ~]# ln -s oldboyfile oldboyfile_soft_link #<==为oldboyfile创建软 链接文件。 [root@oldboy ~]# ls -li oldboyfile* 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile 400789 -rw-r--r--. 2 root root 12 Mar 13 09:23 oldboyfile_hard_link 400791 lrwxrwxrwx. 1 root root 10 Mar 13 09:47 oldboyfile_soft_link -> oldboyfile #<==软链接文件的Inode和文件类型都是不同的,可见软链接文件是单独的文件。 root@oldboy ~]# cat oldboyfile_soft_link #<==查看软链接文件的内容,内容是oldboy- file的内容。 I am oldboy [root@oldboy ~]# readlink oldboyfile_soft_link #<==查看软链接文件的指向, 指向的是oldboyfile。 oldboyfile [root@oldboy ~]# rm -f oldboyfile #<==删除原始文件。 [root@oldboy ~]# cat oldboyfile_soft_link #<==访问软链接会得到提示“找不到目录或文件”。 cat: oldboyfile_soft_link: No such file or directory [root@oldboy ~]# ls -l oldboyfile* -rw-r--r--. 1 root root 12 Mar 13 09:23 oldboyfile_hard_link lrwxrwxrwx. 1 root root 10 Mar 13 09:47 oldboyfile_soft_link -> oldboyfile #<==出现底闪烁故障。
2.目录的软链接示例
目录的软链接示例代码如下:
[root@oldboy oldboy]# mkdir oldboydir #<==创建一个测试文件old- boydir。 [root@oldboy oldboy]# ln oldboydir oldboydir_hard_link #<==为目录创建硬链接尝试 不行。 ln: `oldboydir': hard link not allowed for directory #<==目录不允许创建硬链接,这是为什么呢? [root@oldboy oldboy]# ln -s oldboydir oldboydir_soft_link #<==但可以创建软链接,特别提示:目录的软链接在老男孩的生产场景中经常会用到,硬链接用得不多。 [root@oldboy oldboy]# ls -lirt total 24 98538 -rw-r--r-- 2 root root 0 Oct 28 14:28 oldboyfile_hard_link 98538 -rw-r--r-- 2 root root 0 Oct 28 14:28 oldboyfile 98543 lrwxrwxrwx 1 root root 10 Oct 28 14:28 oldboyfile_soft_link -> oldboyfile 98547 drwxr-xr-x 2 root root 4096 Oct 28 14:34 oldboydir 98549 lrwxrwxrwx 1 root root 9 Oct 28 14:35 oldboydir_soft_link -> oldboydir
提示:代码中加粗部分为本例生成的结果。
小结一下,ln命令不能对目录创建硬链接,但可以对目录创建软链接,针对目录创建软链接,也是生产场景运维中常用的功能。
3.软链接知识小结
·软链接类似于Windows的快捷方式(可以通过readlink查看其指向)。
·软链接类似于一个文本文件,里面存放的是源文件的路径,指向源文件实体。
·删除源文件,软链接文件依然存在,但是无法访问指向源文件路径的内容了。
·失效的时候一般是白字红底闪烁提示。
·执行命令“ln-s源文件软链接文件”,即可完成软链接的创建(目标不能存在)。
·软链接和源文件是不同类型的文件,也是不同的文件,Inode号也不相同。
·软链接文件的文件类型为字母(l),可以用rm命令删除。
·软链接文件不仅可以针对文件,还可以针对目录(企业中常用)。
9.6.4 企业面试:请描述Linux中软链接和硬链接的区别
在遇到这样的面试题时,可从以下几个方面去解答。
1)答分类:在Linux系统中,链接可分两种,一种称为硬链接(Hard Link),另一种称为符号链接或软链接(Symbolic Link)。
2)答概念:硬链接文件与源文件的Inode节点号相同,而软链接文件则相当于Windows下面的快捷方式(Inode节点号与源文件不同)。
3)答创建:默认在不带参数的情况下,ln命令创建的是硬链接,带-s参数的ln命令创建的是软链接。
4)答特点,具体又可分为以下几点来说明。
a)不能对目录创建硬链接,但可以创建软链接,对目录的软链接会经常用到。
b)软链接可以跨文件系统,硬链接不可以跨文件系统。
c)删除软链接文件,对源文件及硬链接文件无任何影响。
d)删除文件的硬链接文件,对源文件及软链接文件无任何影响。
e)删除链接文件的源文件,对硬链接文件无影响,会导致其软链接失效(红底白字闪烁状)。
f)同时删除源文件及其硬链接文件,整个文件才会被“真正”的删除。
5)答案例:硬链接用处不多,可以用来对重要文件做快照以防止误删,对目录建立软链接在工作中很常用,例如,安装软件会使用nginx-1.10作为目录,安装完后设置软链接为nginx,即保持了版本号标识,又方便使用,以及方便后续的软件升级。
9.6.5 Linux系统文件删除原理
1.从ext文件系统的角度描述文件删除的原理
Linux系统上的文件名是存储在父目录的Block里面的,并指向了这个文件的Inode节点,这个文件的Inode节点再标记指向存放这个文件的Block的数据块。我们删除一个文件时,实际上并不会清除Inode节点和Block的数据。只是在这个文件的父目录中的Block里,删除这个文件的名字,从而使这个文件名消失,并且无法指向这个文件的Inode节点。当没有文件名指向这个Inode节点的时候,释放Inode节点和存放这个文件数据的Block块会同时进行,并且会更新Inode MAP和Block MAP,以便让这些位置用于放置其他文件数据。
2.从文件引用的角度深入描述文件删除的原理
Linux系统是通过Link的数量来控制文件是否被删除的,只有当一个文件不存在任何Link的时候,这个文件才会被删除。一般来说,每个文件都有2个Link计数器,既i_count和i_nlink。
i_nlink的意义就是前面讲的文件硬链接的数量,i_nlink可以理解为磁盘的引用计数器;i_count的意义就是当前文件使用者(例如,被进程调用)的数量,i_count可以理解为内存的引用计数器。当为文件创建硬链接的时候,对应i_nlink的数量就会增加,而当一个文件被某个进程调用时,对应i_count的数量就会增加。
通过rm删除命令删除文件,实际上就是减少文件的磁盘引用计数i_nlink的数量。这里就会出现一个问题,如果一个文件正在被某个进程调用,而用户却执行rm操作将文件删除了,那么会出现什么结果呢?
在用户执行rm操作删除文件之后,再执行ls或者其他文件管理命令,将会无法再找到这个文件,但是调用这个被删除文件的进程却在继续正常执行,依然能够从文件中正确地读取及写入内容。这又是为什么呢?
这是因为rm操作只是将文件的i_nlink数减少了,如果没其他的链接,i_nlink就为0了;但由于该文件依然在被进程引用,因此,此时文件对应的i_count数并不为0,所以即使执行了rm操作,但系统并没有真正删除这个文件,因此该文件还会占用磁盘空间,只有当i_nlink及i_count都为0的时候,这个文件才会真正被删除。也就是说,还需要解除该进程对该文件的调用,被rm删除的文件才会真正被删除。
以上讲的i_nlink及i_count是文件删除的真实条件,但是当文件没有被调用时,执行rm操作删除文件后是否还可以找回被删的文件呢?
前面说了,rm操作只是将文件的i_nlink减少了,或者说置0了,实际就是将文件名到Inode的链接删除了,此时,并没有删除文件的实体即Block数据块,如果及时停止机器工作,数据还是可以找回的,但如果此时继续写入数据,那么新的数据可能就会被分配到被删除数据的Block数据块了,此时,文件就是被真正地回收了,那时就是神仙也没有办法了。
Linux文件删除原理的基本示意图如图9-9所示。
图9-9 Linux文件删除原理图
9.6.6 有关文件删除的企业故障案例
下面就来实战模拟文件被删除了(硬链接数为0),但是还有进程调用的情况。本模拟案例用到的知识比较复杂,初学者可以忽略所有的操作步骤,读懂本案例对读者理解文件删除的原理会有一些帮助,等到学习完老男孩的《跟老男孩学Linux运维:Web集群实战》一书后可进一步操作以体会这个案例。
案例1:简单案例,可说明原理(适合于新手读者)。
1)环境准备,命令集合如下:
mkdir -p /app/logs #<==创建用于挂载的目录。 dd if=/dev/zero of=/dev/sdc bs=8K count=10 #<==创建指定大小的虚拟文件(模拟磁盘)。 mkfs.ext4 /dev/sdc #<==格式化。 mount -o loop /dev/sdc /app/logs #<==挂载。 df -h #<==检查挂载结果。
2)创建文件,并用文件填满虚拟磁盘sdc,命令如下:
[root@oldboyedu ~]# cd /app/logs/ #<==切换到目录。 [root@oldboy /app/logs]# touch nginx.log #<==创建空文件。 [root@oldboy /app/logs]# tail -f nginx.log #<==模拟进程持续调用文件。
重新开启窗口执行如下操作:
[root@oldboyedu ~]# cd /app/logs/ #<==切换到目录。 [root@oldboy /app/logs]# cat /etc/services >>nginx.log #<==填满文件直到sdc虚拟磁盘装满。 cat: write error: No space left on device #<==报错“磁盘满了”。 [root@oldboy /app/logs]# df -h #<==查看磁盘状况。 Filesystem Size Used Avail Use% Mounted on /dev/sda3 19G 1.9G 18G 10% / devtmpfs 980M 80K 980M 1% /dev …省略若干行… /dev/loop0 73K 71K 0 100% /app/logs #<==磁盘使用率100%了。
3)此时需要清理磁盘空间,命令如下:
[root@oldboy /app/logs]# rm –f nginx.log #<==删除日志文件这个罪魁祸首。 [root@oldboy /app/logs]# df -h #<==再查看磁盘状况。 …省略若干行… /dev/loop0 73K 71K 0 100% /app/logs #<==磁盘使用率依然是100%。
磁盘文件并没有真的被删除,这是为什么呢?使用lsof命令还是可以查看到被删除的文件:
[root@oldboy /app/logs]# lsof|grep nginx tail 7927 root 3r REG 7,0 57344 12 /app/logs/nginx.log (deleted)
4)切换到第一个窗口,执行Ctrl+c快捷键终止进程对nginx.log的访问(tail-f nginx.log),然后再查看磁盘使用率,命令如下:
[root@oldboy /app/logs]# df -h #<==再查看磁盘状况。 …省略若干行… /dev/loop0 73K 14K 54K 21% /app/logs #<==磁盘使用率降低了。
模拟完成。
案例2:模拟企业级生产案例(适合基础较好的读者)。
操作步骤和命令集如下。
1)安装httpd web服务,命令如下:
yum install httpd -y /etc/init.d/httpd start lsof -i :80 /etc/init.d/iptables stop cd /etc/httpd/conf
编辑配置文件,让日志记录到/app/logs下面,命令如下:
sed -i's@#CustomLog logs/access_log common@CustomLog /app/logs/access_logcommon@g' httpd.conf
2)创建一个小的文件系统,用于存放上述access_log日志,命令如下:
dd if=/dev/zero of=/dev/sdc bs=8K count=10 ls -l /dev/sdc mkfs -t ext4 /dev/sdc tune2fs -c -1 /dev/sdc mount -o loop /dev/sdc /app/logs echo oldboy >/var/www/html/index.html
3)重启httpd服务,确保日志记录到了上述文件系统挂载的/app/log下面,命令如下:
/etc/init.d/httpd restart
4)编写一个循环脚本访问httpd,使得httpd日志充满/app/logs整个空间,命令如下:
for n in 'seq 100000'; do curl -s 127.0.0.1>/dev/null;done [root@oldboy ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 7.2G 2.0G 4.9G 30% / tmpfs 244M 0 244M 0% /dev/shm /dev/sda1 194M 54M 131M 30% /boot /dev/sdc 73K 73K 0 100% /app/log #<==磁盘已满。
5)错误的删除方案,命令如下:
[root@oldboy ~]# rm -f /app/logs/access_log #==删除网站日志,注意这个日志正在被http服务调用。 [root@oldboy ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 7.2G 2.0G 4.9G 30% / tmpfs 244M 0 244M 0% /dev/shm /dev/sda1 194M 54M 131M 30% /boot /dev/sdc 73K 73K 0 100% /app/log #<==磁盘仍然是满的,此时空间并未被释放,原因为何?
查看虽已被删除但仍由httpd进程占用的日志文件名,命令如下:
[root@oldboy ~]# lsof|grep del httpd 6148 root 7w REG 7,0 55260 12 /app/logs/access_log (deleted) httpd 38178 apache 7w REG 7,0 55260 12 /app/logs/access_log (deleted) httpd 38483 apache 7w REG 7,0 55260 12 /app/logs/access_log (deleted) httpd 38484 apache 7w REG 7,0 55260 12 /app/logs/access_log (deleted) httpd 38752 apache 7w REG 7,0 55260 12 /app/logs/access_log (deleted)
根据文件删除的原理来看,因为有进程调用access.log,因此其i_count数量不为0,虽然i_link数量为0了,但是文件依然没被真正删除,所以其占用的空间没有释放。
以下是解决问题的方法。
1)执行快捷键Ctrl+c,停掉模拟访问测试脚本,命令如下:
for n in 'seq 100000';do curl -s 127.0.0.1 >/dev/null;done
2)重启http服务,目的是取消httpd对删除的access.log文件的调用,命令如下:
[root@oldboy ~]# /etc/init.d/httpd restart Stoppinghttpd: [ OK ] Startinghttpd: [ OK ]
通过以下命令可以查看处理的结果:
[root@oldboy ~]# df -h Filesystem Size Used Avail Use% Mounted on /dev/sda3 7.2G 2.0G 4.9G 30% / tmpfs 244M 0 244M 0% /dev/shm /dev/sda1 194M 54M 131M 30% /boot /dev/sdc 73K 14K 55K 21%/app/logs #<==磁盘空间已经释放。
下面介绍一种较好的处理方案。
清空日志而不删除日志,企业中的Web日志都是定期轮询的,并且它还会自动备份且清理过期的日志。示例命令如下:
>/app/logs/access_log
限于本书篇幅,真实的企业级磁盘写满故障的案例仅给出链接地址,方便读者观看。
Web服务器磁盘写满故障深入解析,地址为http://oldboy.blog.51cto.com/2561410/612351。
[1] 参考地址:https://en.wikipedia.org/wiki/Symbolic_link#Storage_of_symbolic_links
9.7 chattr:改变文件的扩展属性
9.7.1 命令详解
【命令星级】 ★★★☆☆
【功能说明】
chattr命令用于改变文件的扩展属性。与chmod这个命令相比,chmod只是改变了文件的读、写、执行权限,更底层的属性控制是由chattr来改变的。
【语法格式】
chattr [options] [mode] [files] chattr [选项] [模式] [<文件或目录>]
说明:
chattr命令以及后面的选项和文件,每个元素之间都至少要有一个空格。
【选项说明】
表9-2针对chattr命令的参数选项进行了说明。
表9-2 chattr命令的参数选项及说明
9.7.2 使用范例
范例9-1:设置只能往文件里追加内容,但不能删除文件。
[root@oldboy ~]# lsattr test #<==lsattr查看文件的扩展属性。 -------------e- test [root@oldboy ~]# chattr +a test #<==+a添加追加属性。 [root@oldboy ~]# lsattr test -----a-------e- test [root@oldboy ~]# rm -f test #<==即使是root用户也无法删除。 rm: cannot remove 'test': Operation not permitted [root@oldboy ~]# echo 111 >>test #<==可以追加文本。 [root@oldboy ~]# cat test 111 [root@oldboy ~]# echo 111 >test #<==但是不能清空文件。 -bash: test: Operation not permitted
范例9-2:对文件加锁,使其只能被执行读操作。
[root@oldboy ~]# chattr +i file1.txt #<==使用+i参数为文件加锁。 [root@oldboy ~]# lsattr file1.txt ----i--------e- file1.txt [root@oldboy ~]# rm file1.txt #<==root用户无法删除文件。 rm: remove regular file 'file1.txt'? y rm: cannot remove 'file1.txt': Operation not permitted [root@oldboy ~]# echo 111 > file1.txt #<==不能清空。 -bash: file1.txt: Permission denied [root@oldboy ~]# echo 111 >> file1.txt #<==也不能追加。 -bash: file1.txt: Permission denied [root@oldboy ~]# chattr -i file1.txt #<==使用-i参数解锁。 [root@oldboy ~]# rm file1.txt rm: remove regular file 'file1.txt'? y #<==解锁后就可以删除了。 [root@oldboy ~]#
9.7.3 安全优化实战
下面利用-a和-i参数为大家讲解chattr在企业中的实战应用。
为避免恶意删除.bash_history历史记录文件或者重定向到/dev/null,又因为系统需要向这个文件写入历史记录,因此采用追加模式,只增不减。命令如下:
[root@oldboy ~]# chattr +a .bash_history #<==为历史纪录文件加上只能追加的属性。
如果希望锁定的文件不能被删除或修改,那么可以使用下面的命令来实现:
[root@oldboy ~]# chattr +i /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab #<==锁定系统关键文件 [root@oldboy ~]# useradd kk #<==添加用户的命令,后面会详细讲解。 useradd: cannot open /etc/passwd #<==说明:做完上面实验的读者,请立即解锁这些文件,因为以后学习都需要修改这些文件。
解锁命令如下:
chattr -i /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab
提示:对于chattr功能的使用,黑客如果知道也能操作,因此,使用chattr的安全性只是相对的。
9.8 lsattr:查看文件扩展属性
9.8.1 命令详解
【命令星级】 ★★★☆☆
【功能说明】
lsattr命令用于查看文件的扩展属性。
【语法格式】
lsattr [options] [files] lsattr [选项] [<文件或目录>]
说明:
lsattr命令以及后面的选项和文件,每个元素之间都至少要有一个空格。
【选项说明】
表9-3针对lsattr命令的参数选项进行了说明。
表9-3 lsattr命令的参数选项及说明
9.8.2 使用范例
范例9-3:查看文件的扩展属性。
[root@oldboy ~]# lsattr file1.txt #<==查看文件默认的扩展属性。 -------------e- file1.txt [root@oldboy ~]# chattr +i file1.txt [root@oldboy ~]# lsattr file1.txt ----i--------e- file1.txt #<==可以看到文件具有i属性。
范例9-4:查看目录的扩展属性。
[root@oldboy data]# ll -d dir2 drwxr-xr-x 2 root root 4096 Nov 4 17:26 dir2 [root@oldboy data]# lsattr -d dir2 #<==使用-d选项可查看目录的扩展属性。 -------------e- dir2 [root@oldboy data]# chattr +i dir2 #<==也可以对目录加锁。 [root@oldboy data]# lsattr -d dir2 ----i--------e- dir2
9.9 本章重点
章节特别提示:本章涉及的有关文件的Inode和Block知识,还是基于CentOS6的ext4文件系统原理进行介绍的,主要原因是考虑到ext4依然很经典,并且与CentOS7的XFS有很多相似之处,更多有关XFS的内容,可参考本书姊妹篇《跟老男孩学Linux运维:核心基础(下)》(计划出版)一书的“磁盘和文件系统”一章的相关内容。
9.10 本章相关问题
1)掌握Linux文件属性中各个列的含义(ls-lhi的结果)及对应知识的概念。
2)磁盘空间不足故障的多重判断和解决方法(面试常考)。
3)请描述软链接和硬链接的特点及区别(面试常考)。
4)请描述Linux系统文件删除的原理(面试常考)。