1 目录与路径
1.1 相对路径与绝对路径
1.1.1 绝对路径和相对路径的定义
- 绝对路径:路径的写法一定是由根目录/写起
- 相对路径:路径的写法不是由根目录/写起,而是相对于当前路径。
1.1.2 几个特殊的目录
.代表此层目录
..代表上层目录
~代表目前用户身份所在的家目录
-代表前一个工作目录
~huyan代表huyan这个用户的家目录
Linux系统中根目录的上层目录是其本身
1.1.3 目录的相关操作
cd:切换目录
如图所示,这里还使用了相对路径和绝对路径,/var/spool/mail是绝对路径,../postfix是相对路径。
pwd:输出当前目录
pwd [-P]
-P:显示出实际的工作目录,而非连接文件本身的目录名
如图所示,不加-P显示的是本身的目录名,而加了-P参数后显示的是实际路径。
mkdir:新建目录
mkdir [-mp] 目录名称
-m:直接设定配置文件案的权限,不需要看umask的脸色
-p:帮助你直接将你所需要的目录递归建立起来(包含上层目录)
示例1:在/tmp下面递归建立数个新目录
如图所示,不加参数的情况下只能新建/tmp的下层目录,加入-P后能够连续新建多层目录,不需要在上层目录存在的情况下才可以新建。
示例2:建立权限为rwxr–r–的目录
rmdir:删除空目录
rmdir [-p] 目录名称
-p:可删除多层目录,连同上层空的目录一起删除
示例1:删除上面示例1中新建的/tmp/test/test1/test2/test3这个多层目录
如图,提示我/tmp无法删除,因为/tmp不是空目录,如图所示,在/tmp下面已经不存在test目录了。mkdir只能删除空目录。如果想将非空目录删除,包括删除子层目录和目录下所有档案,就要用rm -r 目录名这个指令。
示例3:新建非空多层目录,然后用rm -r指令删除该目录
1.1.4 关于执行文件路径的变量:$PATH
举例来说,当我们执行ls指令时,完整的写法应该是/bin/ls,如图所示
在我们执行该指令时,系统在$PATH执行路径变量中依次检索目录,找到该指令的执行文件,执行该执行文件,这就是为什么我们能在任何目录下执行该指令,而系统不会提示我们找不到该指令。当$PATH存储的路径中有多个ls的可执行文件时,先搜寻到的同名可执行文件将被执行。
示例1:查看不同用户的$PATH变量内容
root用户的$PATH变量内容
huyan用户的$PATH变量内容
如图我们知道,不同用户预设的$PATH变量内容不同,默认能随意执行的指令也不同。
示例2:修改huyan1用户的PATH变量内容并删除/usr/sbin目录,观察是否能成功执行ifconfig语句。
ifconfig的可执行文件存储在/usr/sbin目录下,如图所示
修改PATH变量值前,我们先执行ifconfig,发现ifconfig可成功执行。当我们删除PATH变量中的/usr/sbin路径后,执行ifconfig提示command not found,原因很简单,因为ifconfig的可执行文件放置在/usr/sbin路径下,从PATH变量的路径中找可执行文件时,没有/usr/sbin路径了,就自然找不到ifconfig的可执行文件了。
这种情况下,只要我们直接执行ifconfig的可执行文件,而不通过PATH变量去查找,依然能顺利执行ifconfig如图所示
示例3:已知ls指令可执行文件为/usr/bin/ls,将该文件移动到/root,观察ls的执行结果。
huyan1用户的PATH变量如图所示,而ls的可执行文件为/usr/bin/ls,我们用mv指令将该可执行文件移动到/root,被告知拒绝访问。因为huyan1是普通用户,无法访问/root目录。此时我们用su – root指令切换到root用户,如图所示
root用户将/usr/bin/ls移动到/root目录下后退出,回到huyan1用户。我们执行ls指令发现提示ls的可执行文件/bin/ls不存在,也就是在PATH提供的目录中无法找到ls的可执行文件。
注:这里有人会疑惑之前说可执行文件为/usr/bin/ls,这里的提示显示可执行文件为/bin/ls。其实两者都对,因为/bin和/usr/bin互为连接档,/bin的内容就是/usr/bin的内容。
这时我们就要考虑究竟是什么原因导致的,有可能huyan1用户的PATH变量中不含有ls可执行文件的所在目录/root,也有可能是huyan1用户没有权限访问/root目录。接下来让我们注意验证。
如图所示,huyan1用户的PATH变量中加上了/root目录,可还是无法执行ls指令。
如图所示,我又切换到root用户,root用户也无法执行ls指令。在PATH变量中添加/root路径后,能执行ls指令了。
由此说明,造成一个指令无法执行的情况有以下几种:
- 没有安装该指令的可执行文件
- 该用户的PATH变量中没有添加该指令可执行文件所在的目录导致系统找不到
- 该用户没有权限访问指令可执行文件所在的目录
继续上面的实验,切换回huyan1目录,我们用绝对路径的方法执行该指令,发现访问被拒绝,于是切换回root指令,修改/root目录对其他人的权限为rwx,然后返回huyan1用户。此时huyan1用户应该能访问/root目录了。
由于之前已在huyan1用户的PATH变量中添加了/root路径,因此可以直接执行ls指令观察结果
现在huyan1用户能正常执行ls指令了,所以,先前huyan1用户的PATH变量中添加了/root路径也无法执行该指令的原因在于huyan1用户没有权限访问/root目录。
示例4:承接上面的示例3,上面的示例3中,我们将ls的可执行文件从/usr/bin中移动到/root中,并且修改了root用户和huyan1用户的PATH变量,添加了/root路径,并且修改了/root文件夹对huyan1用户的权限为rwx。退出所有用户后重新登录会怎么样呢
如图所示,重新登录root用户,我们发现root用户的PATH变量中没有/root路径存在了,但是依然无法执行ls指令,这说明ls的可执行文件还在/root目录下。将ls的可执行文件移动回/usr/bin中,执行ls指令可以成功执行。
而/root目录对其他人的权限依然是rwx。
这说明PATH变量不是环境变量,修改后重新登录,又会恢复到修改前的样子,但档案的变更和权限的修改却不会因为用户登录登出而变化。
PATH变量中最好不要添加相对路径,因为相对路径随用户当前所在目录的不同,所指代的目录也不同。会导致命令无法使用,所以为了安全起见,不建议将相对路径加入到PATH的查询目录中。
2 文件与目录管理
2.1 查看文件与目录:ls
ls的语法和参数
ls [-aAdfFhilnrRSt] 目录名称
ls [–color={never,auto,always}] 目录名称
ls [–full-time] 目录名称
-a:全部的文件,连同隐藏文件(开头为.的文件)一起列出来(常用)
-A:列出全部的文件(连同隐藏文件,但不包括.和..这两个目录)
-d:仅列出目录本身,而不是列出目录内的文件数据(常用)
-f:直接列出结果,而不进行排序(ls默认会以文件名排序)
-F:根据文件、目录等信息给予附加数据结构,例如:*代表可执行文件,/代表目录,=代表socket文件,|代表FIFO文件
-h:将文件容量以人类易读的方式显示(GB,MB,KB)
-i:列出inode号码
-l:列出长数据串,包含文件的属性与权限等数据(常用)
-n:列出UID与GID而非用户与用户组的名称
-r:将排序的结果反向输出,例如原本按文件名从小到大排序,反向则为从大到小
-R:连同子目录内容一起列出来,等于该目录下所有文件都会列出来
-S:以文件容量大小排序,而不是用文件名排序
-t:按照时间排序,而不是用文件名排序
–color=never:不依据文件特性给予颜色显示
–color=auto:让系统自行依据设置来判断是否给予颜色
–color=always:显示颜色
–full-time:以完整的时间模式(包含年,月,日,时,分)输出
–time={atime,ctime}:输出访问时间或改变权限属性时间(ctime)而非内容更改时间(modification time)
在Linux系统中ls指令是非常常用的指令,当执行ls指令不带任何参数时,默认显示的只有非隐藏文件的文件名,以文件名进行排序及文件名代表的颜色显示。
示例1:将主文件夹下所有文件列出来(含属性和隐藏文件)
示例2:将主文件夹下所有文件列出来(含属性和隐藏文件,不显示颜色,但文件名末尾显示出该文件的类型)
示例3:完整呈现文件的修改时间
如图所示,上图中时间字段变为较为完整的时间格式了。
示例4:仅列出/root目录本身,而不列出目录内的文件数据
如图所示,不加参数-d列出的是目录下的数据,而加入参数-d,列出的是目录本身。
2.2 复制、删除与移动:cp,rm,mv
2.2.1 cp复制档案或目录
cp的语法和参数
cp [-adfilprsu] 源文件 目标文件
cp [options] source1 source2 source3…directory
-a:相当于-pdr的意思(常用)
-d:若源文件为link file,则复制链接文件属性而非档案本身
-f:为强制(force)的意思,若目标档案已经存在且无法开启,则移除后再尝试一次
-i:若目标文件已经存在,在覆盖时会先询问动作是否进行(常用)
-l:建立hard link连结档,而非复制档案本身
-p:连同档案的属性一起复制过去,而非使用默认属性(备份常用)
-r:递归持续复制,用于目录的复制行为(常用)
-s:建立symbolic link,而非复制档案本身
-u:目标文件比源文件旧才更新目标文件
注:若源文件有两个或两个以上,最后一个目标文件一定要是目录。
示例1:用root身份,将/root目录下的.bashrc复制到/tmp目录下,并更名为bashrc。然后重复此操作
如图所示,在CentOS 7中,不必加-i参数,在目标文件已存在的情况下复制,系统会自动询问是否需要覆盖。这是因为,在linux中,定义了cp为cp –i的别名。如下图
所以执行cp和执行cp –i的结果是一样的。如果我们把关于cp –i的别名删掉,再做一遍示例1,结果又会不一样了。
如图,这次,第二次执行命令时在目标文件已存在的情况下并没有询问是否覆盖,加入-i参数才询问。
示例2:切换到目录/tmp,将/var/log/wtmp复制到当前目录且观察属性
如图所示,我们发现复制过来的档案权限不一样了,档案建立的时间也不一样了。如果想将档案的所有特性一起复制过来,可以加-a参数,如图所示
对比这三个档案,我们发现加了-a参数后复制过来的wtmp1权限和创建时间等特性完全和源文件一样。
示例3:复制/etc目录下的所有内容到/tmp目录下
如图所示,我们发现不加-r参数是无法复制目录的,-r表示递归的意思。
示例4:分别对示例1中复制生成的/tmp/bashrc建立hard link和symbolic link
我们再来对比建立连结档后示例1中的/tmp/bashrc和/root/.bashrc的区别
我们发现连结数变了。
示例5:若/root/.bashrc比/tmp/bashrc新才复制过来
如图所示,我去修改了/root/.bashrc档案,使它比/tmp/bashrc更新,然后执行复制命令
如图所示,原来/tmp/bashrc的大小是195bytes,经过复制后变成了207bytes,说明/tmp/bashrc已经被更新了。
示例6:将示例4中的/tmp/bashrc_slink复制称为/tmp/bashrc_slink_1和/tmp/bashrc_slink_2
如图所示,我们发现复制symbolic link连结档,加了参数-d和不加参数-d的复制结果是不一样的,不加参数-d复制过来的是连结档指向的实际档案,而加参数-d复制过来的是连结档本身。
示例7:将/root/.bashrc和/home/.bash_history复制到/tmp目录下
如图所示,可以一次复制多个档案到同一个目录,但最后一定要加上目录,这边我因为所在的目录/tmp正是目标目录,所以用.表示。
示例8:我们能否用huyan普通用户复制/var/log/wtmp档案到/home/huyan目录下呢
如图所示,由于源文件/var/log/wtmp的权限是rw-rw-r–,huyan的身份并不能随意修改文件的所有者和用户,因此虽然能复制wtmp的相关权限与时间等属性,但是与所有者和用户相关的,原本huyan用户无法进行的操作,即使加上-a参数,也是无法达成完整复制权限的。
总之,在用cp指令复制时,我们必须了解以下几点:
- 是否需要完整保留源文件的信息
- 源文件是否为symbolic link file
- 源文件是否为特殊文件,例如FIFO、socket等
- 源文件是否为目录
2.2.2 rm(移除文件或目录)
rm [-fir] 文件或目录
-f:就是强制(force)的意思,忽略不存在的文件,不会出现警告信息
-i:互动模式,在删除前会询问用户是否操作
-r:递归删除,常用在删除目录,是非常危险的参数
示例1:复制/root/.bashrc到/tmp目录下并重命名为bashrc,然后删除/tmp/bashrc
如图,在Linux中同样定义了别名alias rm=’rm -i’。如果我们直接用rm删除该文件,相当于执行rm –i,所以为了对比出区别,这里我先用unalias删除rm的别名。
示例2:将/tmp目录下开头为bashrc的档案全部删除
示例3:将/etc目录整个复制到/tmp目录下,然后将/tmp/etc目录整个删除
如图所示,如果用rmdir指令删除,无法删除非空目录,这时就要用rm –r指令进行递归删除。
这里删除时没有询问,是因为我之前已经取消了rm=’rm -i’的别名设置。但是删除文件不询问太危险了,为了防止误删,我们还是加上别名,执行指令时若不想询问出现,可以用反斜杠\忽略掉alias指定的参数,如图所示。
示例4:在当前目录下创建一个带有-开头的文件,然后删除它
如图所示,touch指令能够创建一个空文件,但为什么第一次输入touch –aaa-创建文件失败了呢,因为系统将-符号识别为参数了,而我们想让它识别为文件名。因此第二句语句我们将路径写成了./-aaa-,这样系统就不会将-识别为参数了,下面使用rm指令也是一样的道理。
如果查阅rm的手册(man rm),我们还能发现另一种方法
如图所示,除了用rm ./-aaa-指令,rm – -aaa-也是可以的。
2.2.3 mv(移动文件与目录,或更名)
mv [-fiu] source destination
mv [options] source1 source2 source3 …directory
-f:force(强制)的意思,如果目标文件已存在,不会询问直接覆盖
-i:若目标文件已存在,会询问是否覆盖
-u:若目标文件已存在,但source比较新的时候才会更新
示例1:复制一个文件,创建一个目录,将文件移动到目录中
示例2:将示例1中/tmp/mytest重命名为mytest2
这样就重命名了。在Linux下面还有另一个有趣的命令:rename。该命令专门针对多个文件名的同时重命名,并非针对单一文件名的更改,这里就不详细介绍了。
示例3:再创建两个文件,再全部移动到/tmp/mytest2中。
注:如果同时移动多个文件到一个目录下,最后一个目标文件一定要是目录。意思是说将所有数据移动到该目录的意思。
2.3 取得路径的文件名与目录名称
完整文件名最长可到达4096个字符,怎样在一个长长的完整文件名中取出文件名和目录名。
示例1:用basename指令和dirname指令找出/etc/sysconfig/network-scripts/ifcfg-ens33这个文件名中的文件名部分和目录部分。
其实,取得文件名或目录名称,一般的用途在写程序的时候用来判断使用的。其他地方用的不多。
3 文件内容查阅
cat:从第一行开始显示文件内容
tac:从最后一行开始显示文件内容,可以看出tac是cat的倒写形式
nl:显示的时候输出行号
more:一页一页地显示文件内容
less:与more相似,但是比more更好的是,它可以往前翻页
head:只看头几行
tail:只看结尾几行
od:以二进制的方式读取文件内容
3.1 直接查看文件内容
直接查看一个文件内容可以用cat,tac,nl这几个命令
3.1.1 cat(concatenate)
cat的语法和参数
cat [-AbEnTv]
-A:相当于-vET的整合参数,可列出一些特殊字符,而不是空白而已
-b:列出行号,仅针对非空白行做行号显示,空白行不标行号
-E:将结尾的断行字符$显示出来
-n:打印出行号,连同空白行也会有行号,与-b参数不同
-T:将Tab按键以^I的形式显示出来
-v:列出一些看不出来的特殊字符
示例1:查看/etc/issue这个文件的内容,并打印行号
如图所示,不加任何参数,只是把文件内容从第一行开始打印出来,加了-b参数,会在行首添加行号,但空白行不计行号。加入-n参数,在行首添加行号,包括空白行。
示例2:将/root/.bashrc的内容完整显示出来,包括特殊字符
在Linux中,tab按键和空格键的效果是一样的,都是一堆空白,我们无法知道两者的差别,通过-A显示特殊字符,就可以知道空白的地方是什么东西了,Tab按键会以^I表示,断行字符则是以$表示。
Windows和Linux的断行字符是不同的,Linux的断行字符是$,而Windows的断行字符是^M$。
当文件行数过多时,用cat来不及查看,配合more或者时less来使用更好。
3.1.2 tac(反向列示)
tac和cat刚好相反,tac是从文件的最后一行开始打印。由最后一行到第一行反向在屏幕上显示出来。
示例1:用tac打印/etc/issue档案和/root/.bashrc档案
3.1.3 nl(添加行号打印)
nl的语法和参数
nl [-bnw] 文件
-b:指定行号指定的方式,主要有两种:
-b a:不论是否为空行,都要列出行号(类似cat -n)
-b t:空行不列出行号,其他行列出行号(类似cat -b)
-n:列出行号显示的方法,主要有三种:
-n ln:行号在屏幕的最左边显示
-n rn:行号在自己字段的最右边显示,且不加0
-n rz:行号在自己字段的最右边显示,且加0
-w:行号字段占用的位数
示例1:用nl列出/etc/issue的内容
不加任何参数情况下,行号在左边显示且不加0,不计空行行号,如图所示
-b a参数作用与cat -n类似,列出包括空行的行号,-b t参数作用与cat -b类似,列出除空行外的行的行号。
如图所示,行号在屏幕的最左方显示,行号在自己字段最右边显示,行号在自己字段最左边显示。
我们可以理解为,在每行行首,默认有6个字段的位置,用于输出行号字段,参数意思中的自己字段,说的就是行号字段本身。然而这个行号字段占用的位数是可以变的,利用-w参数可以设置。如图所示。
nl可以将行号做比较多的显示设计包括位数与是否补0等功能。
3.2 可翻页查看
前面提到的cat,tac,nl命令都是一次性将数据显示在屏幕上,如果数据量大,会造成前面的数据看不到,通过more和less指令可以让我们一页一页地查看大量数据。
3.2.1 more(往后翻动)
中间省略……
如图所示,红框处显示了目前显示出的内容的百分比,你可以在这里输入一些有用的命令:
空格键(space):代表向下翻一页;
Enter:代表向下滚一行;
/字符串:代表在这个显示的内容中,向下查询字符串这个关键字;
:f:立刻显示出文件名以及目前显示的行数;
q:立刻离开more,不再显示该文件的内容;
b或ctrl-b:代表往回翻页,不过这操作只对文件有用,对管道无用;
示例1:在/etc/man_db.conf中向下查询MANPATH关键字
如图所示,输入查询关键字回车之后,more就会开始向下查询该字符串,而重复查询同一个字符串,可以直接按下n即可。
3.2.2 less(前后翻动)
less的用法比more更加有弹性,使用more的时候,我们没办法向前面翻页,只能向后面翻页,但使用less时,就可以使用上,下等按键来前后翻看文件。另外,less也支持向上向下查询关键字。
执行less /etc/man_db.conf之后,页面如图所示,底部显示了当前打开的文件名。
less可以输入的命令:
空格键(space):向下翻动一页;
[PageDown]:向下翻动一页;
[PageUp]:向上翻动一页;
/字符串:向下查询字符串;
?字符串:向上查询字符串;
n:重复前一个查询(与/和?有关);
N:反向重复前一个查询(与/和?有关);
q:离开less,不再显示该文件内容。
3.3 数据选取
我们要把输出的数据做一个简单的选取,取出前面和后面文字的功能,就要使用head指令和tail指令。这两个指令都是以行为单位进行选取的。
3.3.1 head(取出前面几行)
head的语法和参数
head [-n number] 档案
-n:后面接数字,代表显示前面几行的意思
如图所示,直接用head不加参数-n,默认显示的是该档案前10行内容
示例1:显示出/etc/man_db.conf档案中前15行内容
示例2:/etc/man_db.conf档案中后121行不显示
如图所示,这种-n -121写法表示的就是后121行不显示,仅显示前面总行数-121行的行数。比如这个档案总共有131行,那么我用这个写法显示的就是前10行。
3.3.2 Tail(取出后面几行)
tail的语法和参数
tail -n number 档案
Tail -f 档案
-n:接数字,代表显示几行的意思
-f:表示持续侦测后面所接的档名,要等到按下ctrl+c才会结束侦测。
如图所示,不加-n参数默认情况下显示最后10行。
示例1:显示/etc/man_db.conf的最后15行
示例2:/etc/man_db.conf档案的前121行不显示,列出121行以后的数据。
如图所示,和head不同的是,tail中用-n +121表示显示121行以后的数据。
示例3:持续侦测/var/log/messages的内容
如图所示,/var/log/messages这个档案随时会有数据写入,我想要该档案有新数据写入时就自动显示在屏幕上,可以用tail -f对该档案进行持续侦测。输入ctrl+c侦测才会结束。
示例4:显示/etc/man_db.conf的第11~20行
如图所示,用管道命令结合nl,head,tail指令实现。
3.4 非纯文本文件:od
在linux系统中还有一种档案是执行档,这种档案通常是二进制文件,非纯文本。我们用上面提到的这些指令读取二进制文件,会产生类似乱码的数据,显然是不合适的,所以我们用od指令读取二进制文件。
od的语法和参数
od [-t TYPE] 档案
-t:后面可以接各种类型(TYPE)的输出
a:利用默认的字符来输出
c:利用ASCII字符来输出
d[size]:利用十进制来输出数据,每个整数占用size bytes
f[size]:利用浮点数来输出数据,每个整数占用size bytes
o[size]:利用八进制来输出数据,每个整数占用size bytes
x[size]:利用十六进制来输出数据,每个整数占用size bytes
示例1:将/bin/passwd的数据用ASCII的形式输出
后面省略……
最左边第一栏是以8进位来表示byte数,以上面的示例来说,第二栏0000020代表的是第16个byte的内容的意思。
示例2:将/etc/issue的内容以8进位列出存储值与ASCII的对照表
如图,每个字符都在下面列出了对应的数值为何。
利用这个指令,可以将data file或binary file的内容读出来,虽然预设是使用非文本文件,即十六进制的数值来显示的,但是我们可以通过-t c参数将数据内的字符以ASCII形式来显示。
如果对纯文本文件使用这个指令,你甚至可以看到ASCII与字符的对照表,非常有趣。
/root/test是一个纯文本文件,内容如图所示
3.5 修改文件时间或创建新文件:touch
每个档案在linux下会记录许多时间参数,其中有三个最主要的时间参数:
Modification time(mtime):该档案的内容数据变更时会更新这个参数,注意是内容数据不是权限属性。
Status time(ctime):该档案的状态变更时会更新这个参数,比如权限属性的更改
Access time(atime):该档案的内容被取用时会更新这个时间,例如当我们用cat读取这个档案,就会更新它的atime
如图所示,图中的三个时间值分别就是/etc/man_db.conf的mtime,atime,ctime。用ls -l默认显示出来的是mtime。也就是这个内容上次被变更的时间。而刚刚我们用读取文件的指令读取过这个文件,所以它的atime就变成刚刚的时间了。
档案的时间错误可能导致程序无法运行,此时我们可以用touch指令修改。
touch的语法和参数
touch [-acdmt] 档案
-a:仅修订assess time
-c:仅修订档案时间,若该档案不存在则不建立新档案
-d:后面可以接欲修订的日期而不用当前日期,也可以使用–date=”日期或时间”
-m:仅修改mtime
-t:后面可以接欲修订的时间而不用当前时间,格式为[YYMMDDhhmm]
示例1:新建一个空档案并观察时间
如图所示,新建一个新档案,该档案的三个时间都是当前时间。如果在该档案已存在的情况下再次执行touch指令呢,如图所示
在该档案已存在的情况下,再次使用touch指令,会更新该档案的三个时间为当前时间。
示例2:将/root/.bashrc复制成/tmp/bashrc,属性权限完全复制,检查其日期
如图所示,因为是完全复制,所以档案的mtime与原档案的mtime相同。而只是复制没有访问文件,所以原文件和新文件的atime显示的是原文件上次被访问的时间,也一样被复制过来了,只有ctime,因为复制过来状态改变(这里我们是用root复制root的文件,文件所有者和所在组从root变成root,用其他用户复制root的文件也会改变),所以新文件的ctime显示的是当前时间。
所以当复制一个档案时,mtime和atime能完全被复制,而ctime则会显示新文件被创建时的时间,这点和鸟哥的书上写的是不同的。
示例3:修改/tmp/bashrc的档案时间,将时间改为两天前
如图所示,执行touch指令后我们再来观察/tmp/bashrc的时间,发现mtime和ctime由语句执行的当前时间往前推了2天,我执行这条语句时是8月29号15:25,而执行完语句后,mtime和atime变成了8月27号15:25。而ctime被更新成执行这条语句时的时间了。
-d修改时间,不是相对于该档案原本的时间修改的,而是相对于命令执行的当前时间修改的。
示例4:将/tmp/bashrc的时间改为2017/09/15 02:20
如图所示,mtime和atime都被改变成设置的日期,而ctime则被更新为命令执行时的日期。ctime之所以会更新,是因为touch指令修订了时间,时间改变也属于状态改变。所以不管怎么样我们是无法改变ctime的,只能改变atime和mtime为我们设置的时间。
4 文件与目录的默认权限与隐藏权限
之前的学习中我们知道档案有很多属性,包括可读可写可执行(rwx)还有连结档(l),目录(d)和档案(-),还知道了修改档案属性权限的方法chmod,chown,chgrp等。
除此之外,在linux的ext2/ext3中,我们还可以用chattr设置其他系统隐藏属性,而以lsattr来查看系统隐藏属性。最重要的属性是设置档案不可修改的属性,连档案的拥有者都不能修改,这个属性在安全机制上(security)。
示例1:用root用户将/root/.bashrc复制到/home/huyan目录下,并将拥有者改成huyan,群组改为users。
示例2:在/tmp下新建一个目录命名为chapter7_1,并设置权限任何人都可以浏览该目录,但除了huyan以外的其他人不能修改该目录下的档案
4.1 文件默认权限:umask
umask就是指定目前用户在新建目录或档案时的默认权限值。
示例1:查看当前用户在新建目录或档案时的默认权限值
如图所示,我们有两种方法来查看目前用户建立档案的默认权限值,直接执行umask,返回4位数字,第一位代表特殊权限,一般看后三位。而umask -S则是使默认权限值以字符的形式表示。umask的分数代表该默认值需要减掉的权限。
注:这里从默认值中需要减掉的权限,默认值并不是-rwxrwxrwx。
新建档案和新建目录时权限默认值是不同的。
新建档案:-rw-rw-rw-
因为新建档案一般不需要档案可执行,所以权限默认值中没有可执行权限x。最大权限分数为666。
新建目录:drwxrwxrwx
而新建目录时x权限关系着用户能否进入该目录,所以默认权限值必须要有x。最大权限分数为777。
那么我们再来看看,上面用umask查询出来的数值0022后三位代表权限的022。umask的分数代表该默认值需要减掉的权限。因此,目前用户root新建档案和目录时默认的权限是这样的:
新建档案:(-rw-rw-rw-)-(—–w–w-)=-rw-r–r–,即从group和others的权限中减去w权限
新建目录:(drwxrwxrwx)-(—–w–w-)=drwxr-xr-x,也是从group和others的权限中减去w权限。
示例1:新建档案和目录,验证默认权限
如图所示,符合默认权限的设置。
示例2:我希望我新建的档案和目录,组内成员可共同编辑,修改umask值。
因为组内成员可以编辑,所以group的默认权限中就不能拿掉w权限。应该设置umask=002。
如图所示,直接在umask指令后面跟上要设置的umask值,就可以修改了。修改后我们新建档案test1和目录test2,他们的默认权限中组内用户有w权限了。
假如你的umask=003,那么你新建档案和目录的默认权限是什么你知道么?
umask=003表示从其他人的权限中移除wx权限,所以新建档案的默认权限是-rw-rw-r–,新建目录时的默认权限是drwxrwxr–。
关于umask的设定,可以参考/etc/bashrc档案中的内容,有一段是关于umask的如图所示。一般root用户的umask是022,一般用户的umask是002。一般我们不建议修改/etc/bashrc的内容。
4.2 文件隐藏属性:chattr,lsattr
我们用chattr指令配置档案隐藏属性,用lsattr指令查看档案隐藏属性。但这两个指令只能在ext2/ext3文件系统中生效。
为了便于操作,我的CentOS 7中有2个ext2文件系统的挂载点,我们来查看一下。
这两个ext2文件系统挂载点为/var和/media。所以下面的示例都在这两个目录下做。
4.2.1 chattr(配置档案隐藏属性)
chattr的语法和参数
Chattr [+-=] [ASacdistu] 档案名或目录名
+:增加某个特殊参数,其他已存在的参数不变
-:删除某个特殊参数,其他已存在的参数不变
=:设定一定,且仅有后面接的参数
A:设定A属性时,存取档案或目录时访问时间atime不会被更新,可避免I/O较慢的机器过度存取磁盘。对速度较慢的计算机有帮助。
S:一般档案是异步写入磁盘的,设置S参数后变更档案会同步写入磁盘。
a:该档案只能增加数据,不能删除和修改数据。只有root用户才能设置这个参数。
c:自动将该档案压缩,读取时自动解压缩,在存储时会先进行压缩后再存储。
d:该档案不会被dump备份。
i:该档案不能被删除,改名,设定连接,也无法写入和新增数据,对系统安全性有很大帮助,只有root能设置该属性。
s:如果该档案被删除,将被彻底移出硬盘,无法恢复。
u:如果该档案被删除,该档案其实还存在在文件案中,可以救援恢复。
注:属性设定最常见的是i和a,而且很多设定值只能root用户才能设置。
示例1:在/media下创建文件,并加入i的参数,尝试删除看看。
如图所示,设置了i参数之后,连root用户也无法删除该档案,无法重命名档案。
对/media/attr_test档案设置连接档,看是否能通过连接档写入数据。
如图所示,通过symbolic link编辑也无法写入数据。
示例2:将该文件的i属性取消
因为这些属性时隐藏属性,所以需要以lsattr才能看到该属性。最重要的当属+i和+a这两个属性了,+i可以使文件无法被更动。如果是log file这种登录文件,就更加需要+a这个可以增加但是不能修改旧有的数据与删除的参数了。
4.2.2 lsattr(显示档案隐藏属性)
lsattr的语法和参数
lsattr [-adR] 档案或目录
-a:将隐藏文件的属性也一起列出来
-d:如果接的是目录,仅列出目录本身的属性而非目录内的文件属性
-R:连同子目录的数据也一起列出来
示例1:对/media/attr_test设置隐藏属性i并且查看
4.3 文件特殊权限:SUID,SGID,SBIT
我们之前提到的档案权限,为rwx这三个权限,但是我们发现linux系统中个别文件的权限显示了其他字符,如/bin/passwd和/tmp
如图所示,/tmp目录的权限中出现了t,而/bin/passwd的权限中出现了s。
4.3.1 SetUID
当s权限出现在档案拥有者的x权限位置上时,此时s被称为SetUID,简称为SUID的特殊权限,如/bin/passwd档案的-rwsr-xr-x权限。
SUID的限制和功能:
SUID仅对二进制程序(binary program)有效
执行者需要对该程序有x执行权限
本权限仅在执行该程序的过程中有效(run time)
执行者将具有该程序拥有者(owner)的权限,这个是重点。
举例来说,huyan为一般用户,该用户对/etc/shadow和/bin/passwd的权限如下图所示
/bin/passwd是passwd指令的可执行文件,该文件有SUID特殊权限,而使用passwd修改密码会修改/etc/shadow档案,但如图所示,huyan用户对/etc/shadow档案是没有任何操作权限的,那么huyan用户能不能修改密码呢?
如图所示,huyan用户当然能成功修改自己的密码。这是因为/bin/passwd的拥有者是root,且huyan对/bin/passwd有可执行权限,huyan在执行/bin/passwd时会暂时拥有root的权限,这样就能对/etc/shadow档案进行修改了。
另外,SUID仅可用在binary program上(二进制可执行的指令文件或其他文件),不能用在shell script。因为shell script只是呼叫很多binary program来执行而已。另外,SUID对目录也是无效的。
4.3.2 SetGID
当s出现在owner的x位置上时为SUID,那么当s出现在group的x位置上时为SGID。
如图所示,/bin/locate就是一个拥有SGID权限的档案。
与SUID不同的是,SGID可以针对目录来设定。当SGID针对档案来设定时,有以下功能:
SGID对binary program有用
程序执行者需要对该程序有执行的权限
执行者在执行过程中将会获得该程序所在群组的支持
举例来说,当huyan用户执行/bin/locate文件的指令locate时,会去搜寻/var/lib/mlocate/mlocate.db这个档案的内容。
如图所示,huyan用户对/var/lib/mlocate/mlocate.db这个档案是没有任何访问权限的,所以访问被拒绝了。让我们登录root用户来看一下这两个档案的权限。
和SUID一样,huyan用户在执行locate指令时,其实就是执行/bin/locate这个binary program。这个执行过程中,huyan用户会获得/bin/locate这个档案的所属群组slocate的支持,在/var/lib/mlocate/mlocate.db这个档案中有r–权限,这样就能搜寻/var/lib/mlocate/mlocate.db这个档案了。
当目录设定了SGID权限时:
用户若对此目录有r和x权限时,能够进入此目录。
用户在此目录下做操作,将会受到该目录的群组的支持。
若用户在此目录下具有w权限,能新建档案,则用户新建的档案群组与此目录群组相同。
4.3.3 Sticky bit
Sticky bit,简称SBIT,只对目录有效,对档案无效。SBIT对目录的作用是,当用户对目录具有w,x权限,即具有写入权限时,在该目录下建立档案或目录,只有自己和root才能删除。
也就是说,甲用户于A目录是群组或其他人的身份,且拥有该目录的w权限,这表示甲用户对该目录内任何人建立的目录或档案均可进行删除,重命名,移动等操作。但是如果将A目录设置成SBIT权限时,甲用户只能对自己建立的档案或目录做删除,重命名,移动等操作,而无法删除其他人的档案。
4.3.4 SUID,SGID,SBIT的设定
设置方法和一般权限的设置方法一样,在代表权限的数字前再加上一位。我们可以通过数值的累加对一个档案设置它拥有多个特殊权限。
权限 | 代码 |
---|---|
SUID | 4 |
SGID | 2 |
SBIT | 1 |
示例1:SUID试验,将/bin/vim设置成-rwsr-xr-x属性,使huyan用户能用vim去编辑保存一个本身无权限的档案。(针对二进制程序设置SUID权限)
如图,新建一个/tmp/guid_test,用vim编辑器写上内容后将权限设置为000。也就是说这个档案目前只有root可读而且只有root可以强制写入,其他用户无法修改。
为了验证其他用户能否用vim指令修改该档案内容,我们登录huyan,vim修改该档案内容。
如图所示,无法用vim访问/tmp/guid_test。
那么我们现在切换到root用户,将vim命令的可执行文件找出来,为/bin/vim,将该文件设置成SUID特殊权限。如图所示:
然后我们切换到huyan普通用户,看看现在huyan用户是否可以用vim编辑器修改/tmp/guid_test档案了。
用vim打开/tmp/guid_test
如图所示,huyan用户能够修改/tmp/guid_test档案了。但是huyan用户只能通过vim来修改该档案,不能通过其他指令对该档案做查看操作,因为其他指令没有SUID特殊权限,不能暂时拥有档案创建者的身份。
SUID特殊权限:使得在该文件上无权限的其他用户能通过设置了GUID特殊权限的指令暂时获得文件拥有者的权限做相应操作。
注:这个示例要求普通用户huyan必须要有被设置SUID特殊权限的二进制程序的x权限,如果没有x权限,huyan用户无法执行该程序,SUID特殊权限就无法发挥作用了。下个示例也是如此。
示例2:SGID试验,对/bin/ls设置SGID特殊权限,使huyan用户能用ls指令去查看一个本身无权限查看的目录内容。(针对二进制程序设置SGID权限)
用root用户新建/tmp/sgid_test目录,在下面新建多个档案和子目录,并将目录权限设置为050。如图所示,这样除了该目录拥有者以外,只有群组内用户对该目录有r-x权限
我们登录huyan用户,用ls -al指令去查看该目录下内容
如图所示,访问被拒绝。huyan用户无权限访问该目录。因为huyan不是root群组内成员。
我们对ls指令的可执行文件设置SGID特殊权限,使huyan用户能够暂时得到root群组的权限支持,使用ls指令访问该目录。
如图所示,用root用户将ls的可执行文件/bin/ls设置了SGID特殊权限后,我们再登录huyan用户,用ls指令访问/tmp/sgid_test目录看看。
如图所示,访问成功。
示例3:SGID试验,设置示例2中的/tmp/sgid_test目录的权限为SGID特殊权限,普通用户访问该目录并在里面新建档案(针对目录设置SGID权限)
如图所示,登录root用户,设置/tmp/sgid_test目录的权限为2017,即其他人对该目录有rwx权限,且该目录有SGID特殊权限。
切换到huyan用户,在该目录下新建档案/tmp/sgid_test/huyan_test
如图所示,我们发现huyan新建的文件,群组却显示为root,这是由于/tmp/sgid_test目录的特殊权限,导致huyan用户在该目录新建档案受到了目录所属群组root的支持。
示例3:SBIT试验,新建一个测试目录,并设置该目录拥有SBIT特殊权限,让其他用户在该目录下新建删除档案。
root用户登录,新建目录/tmp/sbit_test,并在目录下新建档案和子目录,/tmp/sbit_test目录的权限和目录内容如图所示。其他人对该目录拥有rwx权限,即可对目录下内容做增加,删除和重命名操作。
对/tmp/sbit_test设置SBIT特殊权限
切换到huyan用户,在该目录下做增加删除和重命名档案操作。
如图,huyan用户无法对目录内拥有者不是自己的档案做删除和重命名操作。
如图所示,huyan用户能在目录下创建自己的档案并且做删除和重命名操作。
所以,对目录设置SBIT特殊权限,能使其他用户在该目录下只能操作自己的档案和目录。
当owner,group或others没有x权限时,对档案设置特殊权限,x位置上会出现S或T。
示例5:在示例1中如果将/bin/vim的权限设置为4655会怎么样呢
/tmp/guid_test和/bin/vim的权限如图所示
切换到huyan用户,用vim对/tmp/guid_test档案进行编辑
如图,就算owner对/bin/vim没有x权限,但huyan用户依然可以用vim成功修改/tmp/guid_test档案,这是不影响的。包括作为拥有者的root,也可以执行vim指令来修改/tmp/guid_test档案。
示例6:在示例4中如果将/tmp/sbit_test目录设置为1706会怎么样呢
如图所示,将/tmp/sbit_test的权限设置为1706
登陆普通用户huyan,在/tmp/sbit_test目录下做增加删除修改操作,我们发现huyan无法访问/tmp/sbit_test目录,也无法做增加修改删除操作。这是因为huyan在/tmp/sbit_test目录没有x可执行权限,意味着huyan无法将/tmp/sbit_test作为自己的工作目录。
4.4 查看文件类型:file
如果想知道某个档案的基本数据,例如属于ASCII档案还是data档案,或者是binary,且其中有没有用到动态函式库等信息,可以用file指令来查阅。
如图所示
执行文件的数据多得不得了,其中包括该文件的SUID权限,兼容于x86_64的硬件平台,使用的是linux核心2.6.32的动态函式库等。通过这个指令我们可以简单判断档案的类型。
5 命令与文件的查询
我们常常需要知道一个档案放在哪里,才能对该档案进行一些修改和维护等操作。
5.1 脚本文件名的查询
5.1.1 which(寻找执行档)
which的语法和参数
which [-a] command
-a:将所有由PATH变量中可以找到的指令都列出,而不止第一个被找到的指令名称
示例1:分别用root和huyan搜寻ifconfig这个指令的执行文件名
which是根据用户设定的PATH变量中的目录去查找指令的,所以只能查找执行档。如果查找不到,说明该用户的PATH变量中没有该指令可执行文件所在的目录。
示例2:用which去查找which这个指令的执行文件
如图所示,which是一个命令别名。
示例3:找出cd和pwd指令的完整文件名
现在的CentOS 7中就算是shell内建指令也可以在PATH的目录中被找到,但是鸟哥的linux版本中是找不到的。
5.2 文件名的查找
一般情况下按文件名查找很少用find指令,因为利用硬盘搜索效率太低。一般都是先用locate和whereis指令。因为locate和whereis是利用数据库来搜寻的,所以相当快速。
5.2.1 whereis(寻找特定档案)
whereis的语法和参数
whereis [-bmsu] 档案或目录名
-b:只找binary格式的档案
-m:只找在说明文件manual路径下的档案
-s:只找source来源档案
-u:搜寻不在上述三个项目中的其他特殊档案
示例1:root和huyan分别用which和whereis搜寻ifconfig档案
如图,which找不到的档案用whereis可以找到,因为which只能用来搜索可执行档案。所以当你找不到某些指令的可执行档案时,先用whereis搜索一下。
示例2:找出跟passwd有关的说明文件档(man page)
如图所示,根据档名可以判断,说明文件档是/usr/share/man/man1/passwd.1.gz
Linux将所有档案都记录在一个数据库档案里面,当使用whereis或locate时都会使用这个数据库档案。有时你会发现使用whereis或locate去搜寻档案时会找到已经被杀掉的档案,也会找不到刚刚建立的档案,这是因为数据库档案还未更新。
如图所示,刚新建的档案用whereis查询不到。
5.2.2 locate
locate的语法和参数
locate [-ir] keyword
-i:忽略大小写的差异
-r:后面可接正规表示法的显示方式
示例1:找出系统中所有与passwd相关的档名
中间省略……
如图所示,locate用法简单,只要在后面输入部分文件名,locate就能找出完整文件名(包含路径名称)中带有关键字的所有文件。
但是locate还是有使用上的限制的。Locate查询起来特别快,是因为它是从已经建立的数据库/var/lib/mlocate/里面找的档案,而这个数据库默认是每天更新一次的,所以新建立的档案,数据库还没更新,就无法搜索到。
更新locate数据库的指令:
输入updatedb系统会读取/etc/updatedb.conf这个配置文件的内容,然后去硬盘里进行搜寻文件名的操作,就能更新/var/lib/mlocate的数据库档案了。
5.2.3 find
find的语法和参数
find [PATH] [option] [action]
与时间有关的参数
有-mtime,-atime,-ctime。以-mtime为例
-mtime n:n为数字,意义为在n天之前(一天之内)被更动过内容的档案
-mtime +n:列出在n天之前(不含n天本身)被更动过内容的档案
-mtime -n:列出在n天内(含n天本身)被更动过内容的档案
-new file:file为一个已存在的档案,列出比file还要新的档案的档名
与使用者或组名有关的参数
-uid n:n为数字,这个数字是用户的账号ID,即UID。这个UID被记录在/etc/passwd里,与账号名称对应。
-gid n:n为数字,这个数字是组名的ID,即GID,这个GID记录在/etc/group中
-user name:name为使用者的账号名称
-group name:name为群组名
-nouser:寻找拥有者不存在于/etc/passwd中的档案
-nogroup:寻找群组不存在于/etc/group中的档案
当你自行安装软件时,很可能该软件的属性中没有档案拥有者,就可以用-nouser和-nogroup来查找。
与档案权限及名称有关的参数
-name filename:搜寻文件名为filename的档案
-size [+-]SIZE:搜寻比SIZE还要大(+)或小(-)的档案。这个SIZE的规格有:c代表byte,k代表KB,所以要找比50K还要大的档案,就是-size +50k
-type TYPE:搜寻档案类型为TYPE的档案,类型主要有:一般正规档案(f),装置档案(b,c),目录档案(d),连接档案(l),socket(s)及FIFO档案(p)
-perm mode:搜寻档案权限刚好等于mode的档案,mode指权限分数值
-perm -mode:搜寻档案权限囊括mode的档案。比如说mode=0745,即-rwxr–r-x,那么-rwsrw-r-x(4765)就是囊括了mode。
-perm +mode:搜寻档案权限包含任一mode的权限的档案。比如说mode=0745,即-rwxr–r-x,那么档案权限为-rw-r–r–(0644)的档案也会被列出来,因为rw-被包含在u=rwx中,g=r–被包含在r–中,o=r–被包含在r-x中。
额外可进行的动作
-exec command:command为其他指令,-exec后面可接额外的指令来处理搜寻到的结果
-print:将结果打印到屏幕上,这个动作是默认动作。
示例1:将过去24小时内系统内更新过内容的档案列出
中间省略……
如果是查找3天前的24小时内更动过内容的档案,就输入find / -mtime 3
如果是查找4天内被更动过内容的档案,就输入find / -mtime -4
如果是查找4天前的那一天被更动过内容的档案,就输入fine / -mtime 4
如图所示
+4:查找大于等于5天前变动过内容的档名
4:查找4天前的那一天变动过内容的档名
-4:查找4天内变动过内容的档名
如图所示,是我查找/root目录下4天前的那一天,4天内和4天前(不含第4天)变动过内容的档案档名。
示例2:查询/home底下属于huyan的档案
示例3:搜寻系统中不属于任何人的档案
透过这个指令可以轻易找出那些不太正常的档案。有时候是正常的,尤其是你曾经以源码自行编译软件时。还有就是删除了系统中的账号,而该账号曾经在系统中建立了档案。就可以用nouser来找出这些无主档案。
示例4:找出档名为passwd的档案
利用-name可以搜寻档名
示例5:找出/var目录下文件类型为socket的档名
示例6:搜寻/root目录下含有SUID,SGID,SBIT特殊权限的档案
如图,我们先在/root目录下设置一下有特殊权限的档案
如图所示,在CentOS 7中,执行find /root -perm +7000会出现这样的警告。语法已经改变了。要用find /root -perm /7000
示例7:将示例6中找到的档案用ls -al指令处理一下
如图所示,指令中的{}表示的是find指令查找出来的内容。-exec …… \;这个组合是标配,-exec表示额外指令开始,\;表示额外指令结束。
如图所示,如果学过管道命令,这个示例用管道命令也可以实现。
示例8:找出/root底下包含huyan的档名
find还可以用通配符来查找档名,但是要记得加引号。
如果你要找的档案有条件,有特殊属性,如特殊权限,用户名,组名等,locate是没有办法达成搜寻的,find不但可以指定搜寻的目录(包含次目录),还可以利用参数来找到最正确的档名。find是在硬盘上进行的搜寻,相对locate和whereis来说效率较低。
6 权限与命令间的关系
- 用户能进入该目录,使之成为工作目录的权限
可使用的指令:cd等变换工作目录的指令
所需权限:用户对这个目录有x权限
额外需求:用户想要在这个目录内利用ls查阅文件名,还需要在该目录上拥有r权限
- 用户可以读取目录内档案的权限
可使用的指令:例如本章学到的cat,more,less等
目录所需权限:用户对这个目录至少要有x权限
档案所需权限:用户对这个档案至少要有r权限
- 用户可以修改目录内档案的权限
可使用的指令:例如nano,vi,vim等
目录所需权限:用户对这个目录至少需要x权限
档案所需权限:用户对这个档案至少要有r,w权限
- 用户可以在目录下建立档案的权限
目录所需权限:用户对这个目录至少要有w,x权限
- 用户进入某目录并执行目录下指令的权限
目录所需权限:用户对这个目录至少要有x权限
档案所需权限:用户对这个档案至少要有x权限