“ 本文正在参加「金石计划 . 瓜分6万现金大奖」 ”
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-6 软链接文件的示意图
9.6.3.1 文件的软链接示例
文件的软链接示例代码如下:
[root@centos7 ~]# ll -i neteaglefile neteaglefile_hard_link
34509286 -rw-r--r--. 2 root root 14 Oct 12 18:49 neteaglefile
34509286 -rw-r--r--. 2 root root 14 Oct 12 18:49 neteaglefile_hard_link
[root@centos7 ~]# ln -s neteaglefile neteaglefile_soft_link #创建软链接文件。
[root@centos7 ~]# ll -i neteaglefile*
34509286 -rw-r--r--. 2 root root 14 Oct 12 18:49 neteaglefile
34509286 -rw-r--r--. 2 root root 14 Oct 12 18:49 neteaglefile_hard_link
34509287 lrwxrwxrwx. 1 root root 12 Oct 12 19:21 neteaglefile_soft_link -> neteaglefile #软链接文件的Inode和文件类型都是不同的,可见软链接文件是单独的文件。
[root@centos7 ~]# cat neteaglefile_soft_link #查看软链接文件的内容,内容是neteaglefile的内容。
I am neteagle
[root@centos7 ~]# readlink neteaglefile_soft_link #查看软链接文件的指向,指向的是neteaglefile。
neteaglefile
[root@centos7 ~]# rm -f neteaglefile #删除原始文件。
[root@centos7 ~]# cat neteaglefile_soft_link #访问软链接会提示“找不到文件或目录”。
cat: neteaglefile_soft_link: No such file or directory
[root@centos7 ~]# ls -l neteaglefile*
-rw-r--r--. 1 root root 14 Oct 12 18:49 neteaglefile_hard_link
lrwxrwxrwx. 1 root root 12 Oct 12 19:21 neteaglefile_soft_link -> neteaglefile #出现底闪烁故障。
9.6.3.2 目录的软链接示例
目录的软链接示例代码如下:
[root@centos7 ~]# mkdir neteagledir #创建一个测试目录neteagledir。
[root@centos7 ~]# ln neteagledir neteagledir_hard_link
ln: ‘neteagledir’: hard link not allowed for directory #目录不允许创建硬链接,这时为什么呢?
[root@centos7 ~]# ln -s neteagledir neteagledir_soft_link #但可以创建软链接,特别提示:目录的软链接在生产场景中经常会用到,硬链接用得不多。
[root@centos7 ~]# ll -irt
73033 drwxr-xr-x. 2 root root 6 Oct 12 19:31 neteagledir
34509288 lrwxrwxrwx. 1 root root 11 Oct 12 19:38 neteagledir_soft_link -> neteagledir
提示:代码中加粗部分为本例生成的结果。
小结一下,ln命令不能对目录创建硬链接,但可以对目录创建软链接,针对目录创建软链接,也是生产场景运维中常用的功能。
9.6.3.3 软链接知识小结
- 软链接类似于Windows的快捷方式(可以通过readlink查看其指向)。
- 软链接类似于一个文本文件,里面存放的是源文件的路径,指向源文件实体。
- 删除源文件,软链接文件依然存在,但是无法访问指向源文件路径的内容了。
- 失效的时候一般是白字红底闪烁提示。
- 执行命令“ln -s 源文件 软链接文件”,即可完成软链接的创建(目标不能存在)。
- 软链接文件的文件类型为字母(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)答案例:硬链接用处不多,可以用来对重要文件做快照以防止误删,对目录建立软链接在工作中很常用,例如,安装软件会适用nvinx-1.10作为目录,安装完后设置软链接为nginx,即保持了版本号标识,又方便使用,以及方便后续的软件升级。
9.6.5 Linux系统文件删除原理
9.6.5.1 从ext系统的角度描述文件删除的原理
Linux系统上的文件名是存储在父目录的Block里面的,并指向了这个文件的Inode节点,这个文件的Inode节点再标记指向存放这个文件的Block的数据块。我们删除一个文件时,实际上并不会清楚Inode节点和Block的数据。只是在这个文件的父目录中的Block里,删除这个文件的名字,从而使这个文件名消失,并且无法指向这个文件的Inode节点。当没有文件名的指向这个Inode节点的时候,释放Inode节点和存放这个文件数据的Block会同时进行,并且会更新Inode MAP和Block MAP,以便让这些位置用于放置其他文件数据。
9.6.5.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-7所示。
图9-7 Linux文件删除原理图
9.6.6 有关文件删除的企业故障案例
下面就来实战模拟文件被删除了(硬链接数为0),但是还有进程调用的情况。本模拟案例用到的知识比较复杂,初学者可以忽略所有的操作步骤,读懂本案例对读者理解文件删除的原理会有一些帮助,等到学习完老男孩的《 跟老男孩学Linux运维:Web集群实战》一书后可进一步操作以体会这个案例。
案例1: 简单案例,可说明原理(适合新手读者)。
1)环境准备,命令集合如下:
[root@centos7 ~]# mkdir -p /app/logs #创建用于挂载的目录。
[root@centos7 ~]# dd if=/dev/zero of=/dev/sdc bs=8k count=10 #创建指定大小的文件。
10+0 records in
10+0 records out
81920 bytes (82 kB) copied, 0.00050266 s, 163 MB/s
[root@centos7 ~]# mkfs.ext4 /dev/sdc #格式化。
mke2fs 1.42.9 (28-Dec-2013)
/dev/sdc is not a block special device.
Proceed anyway? (y,n) y
Filesystem too small for a journal
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
16 inodes, 80 blocks
4 blocks (5.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
16 inodes per group
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
[root@centos7 ~]# mount -o loop /dev/sdc /app/logs #挂载。
[root@centos7 ~]# df -h #检查挂载结果。
Filesystem Size Used Avail Use% Mounted on
devtmpfs 900M 52K 900M 1% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.5M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda3 19G 2.1G 17G 11% /
/dev/sda1 253M 157M 97M 62% /boot
tmpfs 182M 0 182M 0% /run/user/0
/dev/loop0 73K 14K 54K 21% /app/logs
2)创建文件,并用文件填满虚拟磁盘sdc,命令如下:
[root@centos7 ~]# cd /app/logs/ #切换到目录。
[root@centos7 /app/logs]# touch nginx.log #创建空文件。
[root@centos7 /app/logs]# tail -f nginx.log #模拟进程持续调用文件。
重新开启窗口执行如下操作:
[root@centos7 ~]# cd /app/logs/ #切换到目录。
[root@centos7 /app/logs]# cat /etc/services >>nginx.log #填满文件直到sdc虚拟磁盘填满。
cat: write error: No space left on device #报错“磁盘满了”。
[root@centos7 /app/logs]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 900M 80K 900M 1% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda3 19G 2.1G 17G 11% /
/dev/sda1 253M 157M 97M 62% /boot
tmpfs 182M 0 182M 0% /run/user/0
/dev/loop0 73K 71K 0 100% /app/logs #磁盘使用率100%了。
3)此时需要清理磁盘空间,命令如下:
[root@centos7 /app/logs]# rm -f nginx.log #删除日志文件这个罪魁祸首。
[root@centos7 /app/logs]# df -h #再查看磁盘状况。
Filesystem Size Used Avail Use% Mounted on
devtmpfs 900M 80K 900M 1% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda3 19G 2.1G 17G 11% /
/dev/sda1 253M 157M 97M 62% /boot
tmpfs 182M 0 182M 0% /run/user/0
/dev/loop0 73K 71K 0 100% /app/logs #磁盘使用率仍然是100%。
磁盘文件并没有真的被删除,这是为什么你?适用lsof命令还是可以查看到被删除的文件:
[root@centos7 /app/logs]# lsof |grep nginx
tail 2263 root 3r REG 7,0 69632 11 /app/logs/nginx.log (deleted)
4)切换到第一个窗口,执行Ctrl+c快捷键终止进程对nginx.log的访问(tail -f nginx.log),然后在查看磁盘使用率,命令如下:
[root@centos7 /app/logs]# df -h #再查看磁盘状况。
Filesystem Size Used Avail Use% Mounted on
devtmpfs 900M 80K 900M 1% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda3 19G 2.1G 17G 11% /
/dev/sda1 253M 157M 97M 62% /boot
tmpfs 182M 0 182M 0% /run/user/0
/dev/loop0 73K 2.0K 66K 3% /app/logs #磁盘使用率降低了。
模拟完成。
案例2: 模拟企业级生产案例(适合基础较好的读者)。
操作步骤和命令集如下。
1)安装httpd web服务,命令如下:
[root@centos6 ~]# yum install httpd -y
[root@centos6 ~]# /etc/init.d/httpd start
Starting httpd: httpd: apr_sockaddr_info_get() failed for centos6
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
[ OK ]
[root@centos6 ~]# lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 1834 root 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1836 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1837 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1838 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1839 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1840 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1841 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1842 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
httpd 1843 apache 4u IPv6 15993 0t0 TCP *:http (LISTEN)
[root@centos6 ~]# /etc/init.d/httpd stop
Stopping httpd: [ OK ]
[root@centos7 /app/logs]# cd /etc/httpd/conf
编辑配置文件,让日志记录到/app/logs下面,命令如下:
[root@centos6 /etc/httpd/conf]# sed -i 's@#CustomLog logs/access_log common@CustomLog /app/logs/access_log common@g' httpd.conf
2)创建一个小的文件系统,用于存放上述access_log日志,命令如下:
[root@centos6 /etc/httpd/conf]# dd if=/dev/zero of=/dev/sdc bs=8k count=10
10+0 records in
10+0 records out
81920 bytes (82 kB) copied, 0.00184793 s, 44.3 MB/s
[root@centos6 /etc/httpd/conf]# ll /dev/sdc
-rw-r--r--. 1 root root 81920 Oct 13 21:40 /dev/sdc
[root@centos6 /etc/httpd/conf]# mkfs -t ext4 /dev/sdc
mke2fs 1.41.12 (17-May-2010)
/dev/sdc is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
16 inodes, 80 blocks
4 blocks (5.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
16 inodes per group
Writing inode tables: done
Filesystem too small for a journal
Writing superblocks and filesystem accounting information: done
This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
[root@centos6 /etc/httpd/conf]# tune2fs -c 1 /dev/sdc
tune2fs 1.41.12 (17-May-2010)
Setting maximal mount count to 1
[root@centos6 /etc/httpd/conf]# mkdir -p /app/logs
[root@centos6 /etc/httpd/conf]# mount -o loop /dev/sdc /app/logs
[root@centos6 /etc/httpd/conf]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
/dev/sdc 73K 14K 55K 21% /app/logs
[root@centos6 /etc/httpd/conf]# echo neteagle >/var/www/html/index.html
3)重启httpd服务,确保日志记录到了上述文件系统挂载的/app/logs下面,命令如下:
[root@centos6 /etc/httpd/conf]# /etc/init.d/httpd restart
Stopping httpd: [ OK ]
Starting httpd: httpd: apr_sockaddr_info_get() failed for centos6
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
[FAILED] #出现这个报错。
[root@centos6 /etc/httpd/conf]# vim /etc/httpd/conf/httpd.conf
#ServerName www.example.com:80 #再这行下面添加一行。
ServerName 127.0.0.1:80
:wq
[root@centos6 /etc/httpd/conf]# /etc/init.d/httpd restart
Stopping httpd: [ OK ]
Starting httpd: [FAILED] #这里提示还是失败。
[root@centos6 /etc/httpd/conf]# tail -5 /etc/httpd/logs/error_log
[Tue Oct 13 21:48:16 2020] [error] (13)Permission denied: could not open transfer log file /app/logs/access_log. #查看日志提示/app/logs/access_log目录没有权限。
[root@centos6 /etc/httpd/conf]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux #关闭SELinux。
[root@centos6 /etc/httpd/conf]# shutdown -h now
[root@centos6 ~]# /etc/init.d/httpd restart
Stopping httpd: [ OK ]
Starting httpd: [ OK ] #现在重启httpd服务正常。
4)编写一个循环脚本访问httpd,使得httpd日志充满/app/logs整个空间,命令如下:
[root@centos6 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
#/dev/sdc分区,没有挂载。
[root@centos6 ~]# mount -o loop /dev/sdc /app/logs
[root@centos6 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
/dev/sdc 73K 14K 55K 21% /app/logs #挂载正常。
[root@centos6 ~]# for n in `seq 100000`;do curl -s 127.0.0.1>/dev/null;done
[root@centos6 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
/dev/sdc 73K 68K 1.0K 99% /app/logs
#磁盘已满。
5)错误的删除方案,命令如下:
[root@centos6 ~]# rm -f /app/logs/access_log
#删除网站日志,注意整个日志正在被http服务调用。
[root@centos6 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
/dev/sdc 73K 68K 1.0K 99% /app/logs
#磁盘仍然是满的,此时空间并未被释放,原因为何?
查看虽已被删除仍由httpd进程占用的日志文件名,命令如下:
[root@centos6 ~]# lsof |grep del
httpd 11018 root 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103074 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103287 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103288 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103495 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103496 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103497 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
httpd 103498 apache 7w REG 7,0 55242 12 /app/logs/access_log (deleted)
根据文件删除的原理来看,因为有进程调用了access_log,因此其i_count数量不为0,虽然i_nlink数量为0了,但是文件仍然没被真正删除,所以其占用的空间没有释放。
以下是解决问题的方法。
1)执行快捷键Ctrl+c,停掉模拟访问测试脚本,命令如下:
[root@centos6 ~]# for n in `seq 100000`;do curl -s 127.0.0.1>/dev/null;done
^C
2)重启http服务,目的是取消httpd对删除的access_log文件的调用,命令如下:
[root@centos6 ~]# /etc/init.d/httpd restart
Stopping httpd: [ OK ]
Starting httpd: [ OK ]
通过以下命令可以查看处理结果:
[root@centos6 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 16G 2.4G 13G 16% /
tmpfs 490M 0 490M 0% /dev/shm
/dev/sda1 976M 65M 861M 7% /boot
/dev/sda3 976M 1.3M 924M 1% /home
/dev/sdc 73K 14K 55K 21% /app/logs
#磁盘空间已经释放。
下面介绍一种较好的处理方案。
清空日志而不删除日志,企业中的web日志都是定期轮询的,并且它还会自动备份且清理过期的日志。示例代码如下:
[root@centos6 ~]# > /app/logs/access_log
限于本书篇幅,真实的企业级磁盘写满故障的案例仅给出链接地址,方便读者观看。
Web服务器磁盘写满故障深入解析,地址为:oldboy.blog.51cto.com/2561410/612…。
【1】参考地址:en.wikipedia.org/wiki/Symbol…。
9.7 chattr:改变文件的扩展属性
9.7.1 命令详解
【命令星级】 ★★★☆☆
【功能说明】
chattr命令用于改变文件的扩展属性。与chmod这个命令相比,chmod只是改变了文件的读、写、执行权限,更底层的属性控制是由chattr来改变的。
【语法格式】
chattr [option] [mode] [files]
chattr [选项] [模式] [<文件或目录>]
说明: chattr命令以及后面的选项和文件,每个元素之间都至少要有一个空格。
【选项说明】
表9-2针对chattr命令的参数选项进行了说明。
表9-2 chattr命令的参数选项及说明
9.7.2 使用范例
范例9-1: 设置只能往文件里追加内容,但不能删除文件。
[root@centos7 ~]# touch test
[root@centos7 ~]# lsattr test #lsattr查看文件的扩展属性。
---------------- test
[root@centos7 ~]# chattr +a test #+a添加追加属性。
[root@centos7 ~]# lsattr test
-----a---------- test
[root@centos7 ~]# rm -f test #即使是root用户也无法删除。
rm: cannot remove ‘test’: Operation not permitted
[root@centos7 ~]# echo 111 >> test #可以追加文本。
[root@centos7 ~]# cat test
111
[root@centos7 ~]# echo 111 > test #但是不能清空文件。
-bash: test: Operation not permitted
范例9-2: 对文件加锁,使其只能被执行读操作。
[root@centos7 ~]# touch file1.txt
[root@centos7 ~]# echo test >file1.txt
[root@centos7 ~]# cat file1.txt
test
[root@centos7 ~]# chattr +i file1.txt #使用+i参数为文件加锁。
[root@centos7 ~]# lsattr file1.txt
----i----------- file1.txt
[root@centos7 ~]# rm file1.txt #root用户也无法删除文件。
rm: remove regular empty file ‘file1.txt’? y
rm: cannot remove ‘file1.txt’: Operation not permitted
[root@centos7 ~]# echo 111 > file1.txt #不能清空。
-bash: file1.txt: Permission denied
[root@centos7 ~]# echo 111 >> file1.txt #也不能追加。
-bash: file1.txt: Permission denied
[root@centos7 ~]# cat file1.txt
test #可以查看。
[root@centos7 ~]# chattr -i file1.txt #使用-i参数解锁。
[root@centos7 ~]# rm file1.txt
rm: remove regular empty file ‘file1.txt’? y #解锁后就可以删除了。
9.7.3 安全优化实战
下面利用-a和-i参数为大家讲解chattr在企业中的实战应用。
为了避免恶意删除.bash_history历史记录文件或者重定向到/dev/null,又因为系统需要向这个文件写入历史记录,因此采用追加模式,只增不减。命令如下:
[root@centos7 ~]# chattr +a .bash_history #为历史记录文件加上只能追加的属性。
[root@centos7 ~]# lsattr .bash_history
-----a---------- .bash_history
[root@centos7 ~]# chattr -a .bash_history
[root@centos7 ~]# lsattr .bash_history
---------------- .bash_history
如果系统锁定的文件不能被删除或修改,那么可以使用下面的命令来实现:
[root@centos7 ~]# chattr +i /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab #锁定系统关键文件。
[root@centos7 ~]# lsattr /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab
----i----------- /etc/passwd
----i----------- /etc/group
----i----------- /etc/shadow
----i----------- /etc/gshadow
----i----------- /etc/inittab
[root@centos7 ~]# useradd xx #添加用户的命令,后面会详细讲解。
useradd: cannot open /etc/passwd
#说明:做完上面实验的读者,请立即解锁这些文件,因为以后学习都需要修改这些文件。
解锁命令如下:
[root@centos7 ~]# chattr -i /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab
[root@centos7 ~]# lsattr /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/inittab
---------------- /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.9 本章重点
章节特别提示:本章涉及的有关文件的Inode和Block知识,还是基于CentOS 6的ext4文件系统原理进行介绍的,主要原因是考虑到ext4依然很经典,并且与CentOS 7的XFS有很多相似之处。
9.10 本章相关问题
1)掌握Linux文件属性中各个列的含义(ll -hi的结果)及对应的知识的概念。
2)磁盘空间不足故障的多重判断和解决方法(面试常考)。
3)请藐视软连接和硬链接的特点及区别(面试常考)。
4)请描述Linux系统文件删除的原理(面试常考)。