首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux便是这个范儿之融于心而表于行(3)

2013-10-18 
linux就是这个范儿之融于心而表于行(3)原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作

linux就是这个范儿之融于心而表于行(3)
原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和本声明。否则将追究法律责
2.3 文件和它与权限的关系

千万不要以为前面所介绍的就是“多用户”的全部因素,毕竟在“澡堂子模型”中,那些只是人的因素。还有一个十分重要的一项,物的因素还没有出现,也就是那些柜子跟锁。要是一定得与Linux中具体的事务相对应的话,那就是文件和目录了。目录和文件在为“多用户”系统中能够形成多个用户和平共处的局面立下了汗马功劳,同时也奠定里坚实的基础。接下来我们就看看它们是怎么回事儿罢。

2.3.1 目录与文件

Linux的目录与文件组织方式是有很大不同的。Windows会将不同的磁盘分区划分为C、D、E、F……等盘,但是在Linux下你找不到。难道Linux不支持磁盘分区吗?不是,它支持。只是磁盘的管理方式不一样,我们后面会详细讲解Linux的磁盘管理方式,现在我们要知道的是,Linux的文件组织方式是从“/”开始的一棵树,所以“/”也被称为根目录。这与在Windows将磁盘分成一个区很像,只是Windows的文件是从“C:/”开始的。

至于什么是目录,什么是文件,这些基本概念我们就不必多说了,相信能够懂得去学习Linux的人是不会不清楚的。在Linux查看文件和目录的命令是ls,它会列出当前目录下所有目录和文件。但是对于第一次使用Linux命令行的用户,可能真的会搞不清楚哪个是文件,哪个是目录。因为在Windows命令行下也会遇到类似这样的困扰。究其原因是很难通过名字看出来目录和文件的区别。虽然从名字上看不出区别,但是从别的地方能看出来,比如在Windows下带有“<dir>”标记的行或使用中括号“[ ]”括起来的名称就是目录,其他的则是文件。Linux的方法要比Windows更高明一些,用颜色区分。一般地,蓝色代表目录,其他颜色代表文件。其实就通用性来讲,Windows的方法更通用,因为Linux使用颜色来区分,就要求显示设备必须支持颜色才行。当然,以现代的科技来整理这种通用性是无意义的,我们很难想像,居然有的显示器不能显示颜色。

其实Linux不仅仅使用颜色来区分文件与目录,还用于区分不同种类的文件。比如绿色代表可执行文件、青色代表符号连接等。但是这些颜色所代表的文件类型并不一定是这样,具体的还要取决于配置文件/etc/DIR_COLORS的规定。若想了解如何修改不同文件类型所对应的颜色,可以查看Linux的连接帮助,具体命令是:

man dir_colors

其实通过这个例子可以看出,Linux的联机帮助不仅仅可以查看具体某个命令的使用方法,还能够查看某个配置文件的配置方法。所以在使用Linux的过程中,一旦遇到困难,要时刻想到那个能够帮助你的“男人”。

前面说过,Linux使用颜色区分文件类型的方法是有些不太通用的,所以有些极端的发行版默认就不会提供这种支持,使得很难区分文件和目录。对于这样的系统则需要给ls命令附加“--color=auto”选项来让它使用颜色来区分文件类型。但是每次都要附加一个这样复杂的选项,显然会让人不爽。要想像大多数发行版那样,直接ls命令就能够有颜色,可以使用alias命令来创建一个命令别名。具体的命令如下:

alias ls='ls --color=auto'

这样,执行ls命令,就等同于执行ls --color=auto命令。为了使得这个设置永远都生效,可以将它添加到/etc/bashrc或/home/<user>/.bashrc文件中。前者对所有用户有效,而后者仅对用户<user>有效。其实那些默认提供颜色功能的Linux发行版,也是通过这个方式开启的功能。

注意,上述方法仅对Linux有效,如果期望将上述知识移植到FreeBSD这样的老牌Unix系统也是可行的,只是ls开启颜色功能的命令选项是“-G”,配置颜色的将不再是配置文件,而是$LSCOLORS环境变量[1]。如果你无法确定,一定要记得使用man,其它的知识点基本等效。

对于其它一些操作文件和目录的命令,在第一章中就已经有了一些介绍,它们具体的执行行为本书就不做过多的介绍了,自己亲自实验一下,要比我码再多的文字都更加有说服力。我懒得写,您懒得看,皆大欢喜!

其实,使用颜色来区分文件类型,有些时候还是比较初级的。而且万一碰到小概率事件,显示终端偏偏不能显示颜色,那且不是要一筹莫展?没关系,接下来我们将要动用真家伙了,搞定了这个,你就完全可以出去跟别人神吹一阵了,这也正是这本书能够诞生的目的之一^_^。

2.3.2 文件属性和权限

这个真家伙就是文件的属性和权限。这里还需要继续“澡堂子模型”,因为文件的属性和权限与用户身份一起,共同完成了Linux系统的多用户权限控制。

如果要是细究Linux多用户权限控制的本质,实际上就是让不同的用户能够访问的文件不同罢了。由于root可以访问任何文件,所以就拥有了至高无上的权利。那么凭什么规定一个用户能访问哪些文件,而又不能访问哪些文件呢?答案是文件自己说了算!

既然是文件说了算,那么我们就看看文件是怎么做到的。在Linux系统中,每个文件都会有一个特定的拥有者(一般是创建它的用户)和所属用户组,这个属于它的固有属性。文件可以利用这两个固有属性来规定它的拥有者或者其所属用户组内的用户是否拥有对它的访问权利,即读、写和执行的权利。此外,为了提高适应性,文件还规定了其他不相关人等,也就是第三个固有属性,对它的读、写和执行的权利。这三个固有属性和三个权利合起来,就构成了文件的针对系统中所有用户的访问控制,也就形成了Linux的“澡堂子模型”。

其实如果仔细分析,Linux的这种访问控制特性,能够形成“澡堂子模型”也只是一种特列罢了。因为只要规定了文件针对用户的读、写和执行权利,可以构建任何模型。但是最终能够形成这个模型确并不巧合,而是经过精心设计和经历过历史考验的模型,是一种成功的模型,可以继往开来的模型。当然,如果你有一天能够设计出比现有“澡堂子”更好的也没什么问题。不过有点扯远了,我们还是回过头来继续看看从什么地方能查看文件的属性和权限吧。

使用ls命令的-l选项,就能查看,如下所示:

……

-rwxr-xr-x. 1 root root 27776 Apr 17 2012 arch

lrwxrwxrwx. 1 root root 4 Oct 21 00:19 awk-> gawk

-rwxr-xr-x. 1 root root 26264 Apr 17 2012 basename

-rwxr-xr-x. 1 root root 938736 Apr 23 2012 bash

-rwxr-xr-x. 1 root root 48568 Apr 17 2012 cat

……

我们单独拿出来一行,分析一下它的结构,如图2.1所示:

linux便是这个范儿之融于心而表于行(3)

图2.1 文件属性的展现结构

在这些属性中比较重要的自然就是最开始的文件类型和权限属性了,那些xxoo都代表什么呢?图2.2做了详细的展示:

linux便是这个范儿之融于心而表于行(3)

图2.2 文件类型和权限

第一个字符用于描述文件类型,可有的取值是:-、d、l、b、c、s和p。“-”代表这是一个普通文件;“d”代表这是一个目录;“l”代表这是一个软连接,硬连接没有特殊标记;“b”和“c”都代表着设备文件,“b”是块设备,如磁盘等保存大块数据的设备,“c”是字符设备,如鼠标、键盘等需要连续串行读写的设备;“s”代表是套接字(socket)文件,一般使用Unix domain socket的时候会创建这种类型的文件;“p”命名管道文件。余下的部分则对应着不同用户群体的读、写和执行权限。所以,根据这些定义,图2.2所展示的是一个普通文件,允许拥有者读、写和执行(如果是程序),允许相同用户组的用户读和执行,允许其他用户读和执行。根据图2.1所展示的这个文件的拥有者是root,所属用户组是root。

那么现在Linux的权限控制已经很明晰了。当某个用户需要访问某个文件时,系统就读取这个文件的属性和权限信息与当前用户的进行对比,来确定当前用户是文件的拥有者或与其所属用户组同组,亦或是毫无关系。然后根据这些比对结果和用户所执行的动作来判断是否满足权限要求。这样也就引出了文件权限与命令的一些关系,因为Linux系统中一个文件是否是可执行文件是通过属性来决定的,而不是扩展名。

对于目录,“x”权限可以控制用户是否能够打开它,只有具备“x”权限的用户才能打开这个目录。而如果要想使用ls命令来查看这个目录下的文件列表,则必须拥有“r”权限,否则即便能进入,也无济于事。那么要想在目录中创建文件呢?显然要拥有“w”权限了。

对于其他类型的文件,若想读取,则需要“r”权限,若想能够使用编辑器编辑,就必须同时具备“r”和“w”这两个权限。如果一个文件是shell脚本或其它可执行的文件,要能够被执行,应当具备“x”权限。

一些细心的人可能会意识到,上述所展示的内容始终缺乏一种属性,这种属性是看不见的属性,即隐藏属性。为什么上述三个图中我们都没有介绍过隐藏属性呢?原因就因为它是隐藏的,而我们并没有使用命令让它现身。要想见到隐藏属性,就必须看到隐藏文件才行。这个很好办,给ls命令附带“-a”选项即可。如果同时想看到全部的属性和权限信息,可以使用“ls –al”命令,结果如下:

……

-rw-rw-r--. 1 jagen jagen 5131936 Jun 13 2012 nginx-1.2.7.tar.gz

-rw-------. 1 jagen jagen 746 Dec 6 01:22 .bash_history

-rw-r--r--. 1 jagen jagen 18 Apr 23 2012 .bash_logout

-rw-r--r--. 1 jagen jagen 176 Apr 23 2012 .bash_profile

-rw-r--r--. 1 jagen jagen 124 Apr 23 2012 .bashrc

……

其中文件名前面带有点号“.”的即是隐藏文件,而实际上文件的隐藏属性就是在文件名前添加“.”。

2.3.3 文件连接

在这些属性中可能最让人困惑的应该是“连接数”这个属性了。要解释清楚这个属性就要搞清楚Linux保存文件的方法。Linux所使用的文件系统是一种基于inode的文件系统。inode翻译成中文是索引节点,是所有类Unix操作系统中的一种数据结构,也是这类操作系统中文件系统的核心,每一个新创建的文件都会被分配一个inode,且每个文件都有一个唯一的inode编号。我们可以将inode简单理解成一个指针,它指向的是文件所在磁盘中的物理位置。图2.1所展示的这些文件属性也保存在inode中。系统是通过inode定位每一个文件的,而不是文件名。所以通常情况,为了提高文件系统的执行效率,访问过的文件的inode会被缓存在内存中。那么“连接数”这个属性其实就是inode的引用计数。为什么要增加这个引用计数呢?原因就在于Linux允许一个文件拥有多个名字。也就是说,文件名只是相当于是对inode的一次引用。我们大多数时候所见到的“连接数”都是1,这说明大多数文件都只有一个名字。那么什么时候文件会有多个名字呢?在使用ln命令建立文件连接的时候。ln命令可以建立两种文件连接——硬连接和软连接,其中软连接也叫符号连接。其实软连接不是真正的连接,与Windows中的快捷方式类似,只是一个普通的文件,需要额外增加一个“-s”命令选项来创建。比如执行命令:

$ ln -s /bin/bash sh

就会创建一个新的软连接sh指向/bin/bash,使用“ls -l”命令,可以查看到类似这样的结果:

……

lrwxr-xr-x. 1 jagen jagen 9 Oct 21 21:59 sh -> /bin/bash

……

软连接的文件属性和目标文件属性完全不同,按照系统设计,软连接也要占据一个新的inode。也就是说软连接是一个新的文件,不影响inode的引用计数。那么硬连接呢?不使用“-s”命令选项创建的就是硬连接。比如执行命令:

$ ln /bin/bash bash

就会创建一个名为bash的硬连接到/bin/bash。使用“ls -l”命令,可以查看到类似这样的结果:

……

-rwxr-xr-x. 2 root root 938736 Apr 23 20:12 bash

……

硬连接的属性跟目标文件的属性完全相同,因为引用的是相同inode,仅仅将inode的引用计数进行了+1操作。需要注意,有些人可能无法完成这个实验,系统会提示:

ln: creating hard link `bash' => `/bin/bash': Invalidcross-device link

这是因为硬连接要求必须与目标文件在同一个分区中,具体为什么是这样,留给大家思考一下。此外,即便有人执行成功了,想删除新创建的这个硬连接却发现不行,因为权限不够。毕竟硬连接是直接引用了目标文件的inode,它的所有属性也都引用进来了。

好了,根据软连接和硬连接的这些异同,我们就能有下面的一些推断:

l输入删除文件连接的目标文件,则软连接会失效,而硬连接则仅是“连接数”-1。

l软连接可以创建在任何位置,包括网络,而硬连接则不行,目标文件与连接文件必须在同一磁盘分区内。

l软硬连接在使用的时候区别不大,都相当于是一个文件具有不同的路径和文件名。

那么Linux,或者说Unix提供连接这玩意儿有什么用呢?其实用途很明确,就拿软连接来说,它跟Windows的快捷方式是一样的东西,只是要领先Windows几条街了。至于硬连接就更加高明了,它使得同一个文件能够拥有不同的路径,还能防止恶意被删除,因为删除动作只不过是引用计数-1,这可以很大的提高文件系统的可靠性。文件连接的作用还远不止这些,具体的我们就不一一列举了,大家再日后的工作中发明和创造吧,这也是Linux乐趣。

2.3.4 修改文件的属性和权限

光知道文件有那些属性和权限是不能使用Linux系统的,因为那样你就只能被动的接收系统默认给你的那些。面对一份完全没有创意的工作,我相信再有激情的人也很快会灯尽油枯,提不起精神来。为了避免这种山穷水尽的事情发生,必须掌握操纵Linux文件属性和权限的技能。接下来我们就说道说道这些。

首先说明,要想操纵文件的属性和权限,首先你必须具备对文件的写权利,或者是root。在文件的这些属性中,最容易操纵的属性是文件名和最后更新时间。修改文件名的命令是mv,看起来挺奇怪,实际上是“move”的缩写,如果你学过英文的话,应该知道是move的含义是移动。没错!mv就是移动文件。因为将文件移动到一个新的名字上等同于改名,所以linux就没有单独提供更改文件名的命令。需要注意,单独修改文件名并不会改变文件的最后更新时间属性。要修改这个属性,需要使用touch命令。只要将要修改更新时间的文件名作为参数传递给它即可。

修改文件所属用户组使用的命令是chgrp,但是这个命令不是很常用。为什么呢?因为另外一个命令,chown也能够完成跟他一样的活。从命令的字面含义看,chown是更改文件的拥有者。没错,它就是干这个的。这个命令的格式是:

chown [-R] username filename

或者

chown [-R] username:group filename

当使用第二种格式的时候,会连同文件所属的用户组一同修改。其中“-R”参数是可选的,且仅在修改目录的时候有用,意思是递归性修改,也就是将目录下的所有文件包括子目录在内全都更改指定的拥有者。其实在Linux的很多命令里,只要涉及到了对目录的操作,都会有“-R”这个选项。只是比较坑的是有时候是“-r”,很难让你摸到它的脉门。所以永远别要忘了Linux中的那个“男人”,一旦你吃不准的时候就要man一下它。

改变文件权限需要使用chmod命令,用于修改那些xxoo(文件类型不同修改)。这个命令的花样比较多,可以划分为数字法和文字法。我们先介绍数字法。

所谓数字法就是使用数字来代替r、w和x。r等同于4,w等同于2,x等同于1。权限组合就用这些数字的和来表示。比如r-x权限就是5、rw-权限就是6、而rwx权限就是7。根据前面的介绍,一个文件拥有对三种角色的权限设定,即拥有者、所属组和其他,就需要使用三个数字来表示。比如777,对应的类型和权限属性是“-rwxrwxrwx”,而755对应的则是“-rwxr-xr-x”。所以使用数字法修改权限,就使用类似这样的命令:

$ chown 700 .bashrc

使用“ls–al”命令来查看.bashrc文件的权限,应该是“-rwx------”。

至于文字法就比较复杂了,但是非常直观。首先引入了四个字母u、g、o和a,分别代表拥有者、所属组、其他和全部。接着引入三个操作符+、-和=,分别代表增加、减去和设定。如果给拥有者增加“w”权限,可以使用“u+w”代表。或者联合使用,比如“u=rwx,go=rx”则代表给拥有者设定“rwx”权限,给所属组和其他设定rx权限。举个例子,去掉.bashrc文件的执行权限,可以这样操作:

$ chmod a-x .bashrc

$ chmod ugo-x .bashrc

也可以

$chmod -x .bashrc

对于最后这种方式,使用了默认操作对象。但是每个操作的默认操作对象还不尽相同。我们建议你亲自实验一下,这样记得会更牢靠一些。

2.3.5 深入文件权限

其实Linux的文件权限不止是r、w和x,还包括s和t这两个特殊的,它们与系统的账号和系统的进程相关。

s这个标记可以出现在文件拥有者的x权限上,也可以出现在文件所属组的x权限上。这两种情况是有些差别的。前者被称为Set UID,简称SUID,而后者被称为Set GID,简称SGID。

执行命令“ls -l /bin/su”后,能够看到的su这个命令的文件权限是“-rwsr-xr-x”,这就是SUID了。SUID权限拥有这样的功能:

lSUID仅对二进制程序有效;

l执行者对于该程序具有x的可执行权限;

l执行权限仅在执行该程序的过程中有效;

l执行者将具有该程序拥有者的权限。

比如su这个命令,无论任何人,执行了它都将具有root权限,因为它的拥有者是root,这是这个权限仅在执行的su命令中有效。这也是su命令能够切换用户权限的实现原理。

设置SUID权限可以使用“u+s”来进行。SUID在Linux系统中是非常常见的,那些需要提供给普通用户,但是有需要root权限才能正确执行的程序基本上都拥有SUID,比如passwd、mount等命令,也是实际用户和有效用户发生不一致的触发条件。这样做并没有未必系统的安全意图,因为能够赋予SUID权限的程序都是经过谨慎设计的。实践证明它们并没有引入什么安全问题。

相对于SUID,SGID就比较少见个了。比较典型的是/usr/bin/locate命令,它们权限是“-rws--s—x”,这就是SGID了。要设置SGID权限,可以使用“g+s”来进行。SGID权限的功能是这样的:

lSGID对二进制程序有效。

l执行者对于该程序具有x的可执行权限。

l执行者在执行的过程中将会获得该程序所属用户组的支持。

SGID用在locate命令上,是期望任何用户在执行这个命令的时候能够读取mlocate.db文件的内容,这个文件位于/var/lib/mlocate/mlocate.db,它与locate命令有用相同的用户组,而且用户组具有读权限,其他用户没有任何权限。

SGID除了用在二进制程序外,还能够用在目录上。当一个目录设置了SGID权限后,它将具有如下功能:

l用户若对于此目录拥有r与x权限时,该用户能够进入此目录。

l该用户在此目录下的有效用户组将变成该目录的用户组。

l若用户在此目录下具有w的权限,则用户所创建的新文件的用户组与此目录的用户组相同。

依据这一特性,进入这类目录的用户就会发生有效用户组和实际用户组不一致的情况。而另外一种导致有效用户组和实际用户组不一致的情况是使用newgrp命令。而有效用户组所起到的作用就在于其创建文件时文件的用户组。

既然文件的拥有者和用户组的x权限可以有s,是不是其他用户的x权限也可以有s呢?答案是肯定的。只是这个时候不能是s,而是t了。所以设置这个权限应该使用“o+t”来进行。t权限的名称是Sticky Bit,简称SBIT。仅对目录有效。SBIT对于目录的作用如下:

l用户若对此目录拥有w和x权限,即拥有写的权限。

l当用户在此目录下创建了文件或目录,仅有自己与root才有权利删除文件。

换句话说,当用户U在目录D下创建文件F,若D拥有SBIT权限,那么仅有用户U和root能删除文件F。

SBIT应用的典型例子是/tmp目录。这个目录允许任何用户在里面创建文件,但是为例避免创建的文件被其他人误删除,则设置SBIT权限,使得自己创建的文件仅能让自己或root删除。不相信你可以做个实验看看,不过去确认你的/tmp目录的权限是不是“drwxrwxrwt”,如果不是这样,请使用“chmod o+t /tmp”命令来修改。

虽然我们之前介绍设置SUID、SGID和SBIT权限使用的都是文字法,其实使用数字法也是能够设置的。只要将原来的3位数字扩展成4位即可。SUID用4代表,SGID用2代表,SBIT用1代表。它们放在权限数字的最开头。比如我们要设置SUID,可以写成“4755”,要设置SGID,可以写成“2755”。

2.2.6 文件的基本操作

了解了文件与权限的关系之后,其实有关Linux管理文件的难点就没有了,余下的基本操作都相当简单,这里做一些简单的介绍。

最常用的文件管理命令只有5个,而且也非常简单,就是ls、cd、cp、rm和mv。介绍这些命令如何使用是相当无聊的事情,所以还是留给你们参考Linux的联机帮助(man)去吧。这里说明一下Linux的这些命令为什么会这么精简可能会更有趣一些。

其实什么事情能够有精简,无外乎只有一个原因,就是一个“穷”字。想当年Ken Thompson爷爷也是跟你我一样的屌丝,买不起流行配置的电脑,只能使用一台早已被人遗弃在角落里的“破烂”来开发Unix。由于内存很吃紧,日子必须得算计着过,什么地方的主意都得打,甚至连命令都不放过。由两个字母构成的命令就是在那个时候被发明的,因为如果使用一个字母做命令的话,字母实在是不够用了。但是为什么到了现在内存都按G算了,也没有使用更加清晰易懂的命令名呢?这自然离不开一个“惯”字。人是有惯性的,一旦养成了习惯就很难改变,而且在使用命令行进行操作的时候不是还能少输入呢吗?正所谓“穷且益坚,不坠青云之志”,在环境恶劣的条件下诞生的系统反而会更容易让人接受,更具性价比。从这些两个字母构成的命令上就能看出这其中的奥妙。当然,也不是所有命令都沿袭了两个字母构成,比如创建目录的mkdir已经不是当年那个样子了,因为在好记和精简方面,有时候也需要取舍。另外,传统UNIX风格的命令行选项[2]也体现了这种精简之风,也非常值得大家悉心体味一番。

Linux中有几个特别的目录名,分别是:“.”、“..”、“-”和“~”。

其中在任何目录下都能被看到的是“.”和“..”,这个熟悉Windows的人应该并不陌生,而且它们与在Windows下的定义是相同的,即分别代表当前目录和上一级目录。比较有趣的一个问题是在Linux的根目录“/”下有“..”目录吗?答案是有的。在根目录“/”下“..”和“.”是完全相同的,都代表根目录“/”。由于“.”目录的存在,使得每一个目录的“连接数”属性为2;由于“..”的存在,目录中每增加一个子目录,其“连接数”属性+1;所以“.”和“..”就是实际的文件硬连接的例子。

目录“-”和“~”从来没有出现在磁盘中,它们实际上只是cd命令的一个特殊参数。“-”代表上一个工作目录,而“~”则代表当前用户的home目录。由于它们的特殊性,不建议将真是的目录名命名为“-”或“~”,因为这样你将永远无法使用cd命令进入它们。

我相信有人一定会奇怪,为什么最常用的文件操作命令是5个,删、查、复制、移动、跳转都有了,为什么偏偏没有创建呢?其实在Linux下,普通用户基本上是很少要去创造文件的,因为文件不是已经存在了就是由程序生成的。所以诸如mkdir这样的创建命令并不在最常用的范围之内。

2.3.7 搜索文件

Linux系统一共提供了5个搜索文件的命令,它们各有各的特色,可以满足不同场合的需求。其实大部分人只要能够掌握2到3个就已经足够了,真正能够掌握5个的人没有几个。本书非常希望它的读者能够被称为少数人,所以就在这里将5个命令全都给汇在一起了。

在Linux中搜索文件最简单快速的方法是使用whereis命令。说他简单,因为只要执行:

$ whereis ls

就可以所搜到“ls”命令以及它的联机帮助文档所在的位置。说他快速,是因为它根本不在磁盘中漫无目的的乱找,而是在一个数据库中(/var/lib/mlocate/)查询。这个数据库是Linux系统自动创建的,包含有本地所有文件的信息,并且每天通过自动执行updatedb命令更新一次。也正是因为这个数据库要每天才能更新一次,就会使得whereis命令的搜索结果有时候会不准确,比如刚添加的文件可能搜不到,而刚删除的文件还会出现在结果中。如果需要立即获得准确的搜索结果,可以先手动执行一下updatedb命令,但是这样显然已经丧失了whereis本身高效的特性。

虽然whereis命令既简单又高效,但是功能却很有限。它只能用于搜索可执行文件、联机帮助文件和源代码文件。如要获得更全面的搜索结果,可以使用locate命令。locate命令也跟whereis类似,且它们使用的是相同的数据库。但是locate使用了十分复杂的匹配语法。如果只是这样:

$ locate ls

就会匹配到无论是文件名中还是路径中出现过“ls”的文件,有些时候这样的结果是不能使用的,因为太多了。如果要精确搜索,可以这样:

$ locate -b "\ls"

会将所有文件名为“ls”的文件路径列出。在我的系统中能搜到三条记录。由于locate与whereis拥有相同的机制,所以也会有相同的缺点。为了速度,你就要牺牲准确性。

其实在Linux中更为常用的搜索命令是which。这个命令比上述所有命令都要简单,它只是在$PATH环境变量(用于保存可执行文件的默认搜索路径)中指定的路径来搜索可执行文件的所在位置。它一般用来确认系统中是否安装了指定的软件。比如要确认是否安装了gcc,可以使用命令:

$ which gcc

来确认。如果已经安装了gcc,那么就会返回gcc程序的路径,否则就会报错。

type命令比较特别,从名字上看不出它有什么搜索文件的能力。实际上type命令是用来判断一个命令是否属于shell内置的。如果是非内置的shell命令,并且使用了type的-p选项,type就相当于是which命令了。所以从这一点上,就将type归纳为搜索命令了。这一点可是我不外传的秘密,我只告诉了你们。

最后一个搜索命令,也就是超级无敌的find命令。它无所不及,只是效率极差,因为它没有耍滑头弄什么数据库,而是非常地道的从磁盘中胡乱找一气,而且还一丝不苟的,不慢的话对得起谁呢?想想我都觉得累得慌。

find命令的强大在于如果我要让大家能融汇贯通它的使用,肯定需要耗费这本书至少30%的内容才能够达成。如果你认为我有忽悠的嫌疑,那么我举个例子你就明白了。比如我要找到在3天前的那天发生变化的所有文件,我可以使用命令:

$ find / -mtime 3

如果要查询三天内发生变化的所有文件,可以使用命令:

$ find / -mtime -3

如果要查询三天以前发生变化的所有文件,可以使用命令:

$ find / -mtime +3

对于这样的精确查询条件的设定,find还有许多许多,而这仅仅是查询条件。find不仅仅可以设置十分精确的查询条件,还能规范对找到的文件做什么动作。比如我们要列出一天以内变化的文件的详细信息,可以使用类似这样的命令:

$ find / -mtime -1 -exec ls -l {} \;

很多人在学习find命令的这一部分时,总是搞不清楚-exec后面的那部分怎么写。我这里可以简单介绍一下。

-exec是find命令对找到的文件执行的动作,这个动作就是对找到的文件执行命令。这个执行的命令就写在了它的后面,在我们的例子中是“ls -l {}”。其实最迷惑人的就是这里,很多人搞不清楚“{}”是什么意思。其实它就是一个站位符,在find命令的执行过程中会不断的被替换成当前找到的文件。这样在本例中ls命令就完整了,能够显示想要的文件的详细信息了。具体的命令执行过程弄清楚之后,就是后面的这个“\;”,更加让人摸不到头脑。为什么呢?因为Linux的联机帮助上说-exec的命令结束标记是“;”。但是我们在实际使用过程中如果真是这样用的,就总是报错,find拒绝工作。其实这是shell的错,“;”在bash(Linux的默认shell,几乎所有发行版本都是这样)环境中有特殊含义,所以需要使用“\”来转义一下。

2.3.8 对文件打包压缩

一个完整的软件,需要有许多不同类型的文件构成:库文件、配置文件、可执行文件等;一个源代码,需要有许多不同的模块代码构成:数据模块、控制模块、视图模块等。少则几十,多则上百。

这么多的文件,如果需要你拷来拷去是不是很烦?很烦怎么办?打包!

这么多的文件是不是很大,通过网络下载会不会很费时间?时间有限等不急怎么办?压缩!

你选择了Linux,这些就都不是问题。打包和压缩一个命令全都解决。这个命令是什么呢?tar!如果你经常使用Linux,一定会遇到很多类似:*.tar.gz、*.tar.bz2或*.tar.xz这样的文件。因为很多软件是以这种文件形式发布的,甚至Linux内核也是如此。这些文件统称都叫“tar”包,其不同的结尾,表明所使用的压缩算法不同。压缩比从低到高的排序是gz<bz2<xz,而压缩速度则正好相反gz>bz2>xz。鱼与熊掌是永远都不能兼得的。

解压缩“tar”包是非常简单,只需要使用这样

$ tar -vx -f filename

$ tar -vxf filename

就可以解压缩所有类型的“tar”包,注意,filename就是你要解压缩“tar”包的文件名,而且使用后一种形式的时候,命里选项里的f一定要放在最后[3]。

创建“tar”包可能稍微有些麻烦,但是也只是要比解压缩的时候多一个命令选项,而这个多出来的命令选项就是所采用的压缩算法。z代表gz,j代表bz2,J代表xz。所以要创建一个“tar”包,可以使用类似这样的命令:

$ tar-zcvf filename.tar.gz FILES

$ tar-jcvf filename.tar.bz2 FILES

亦或

$ tar-Jcvf filename.tar.xz FILES

其中FILES代表要被打包和压缩的文件或这目录名称。

除了tar这个打包压缩工具之外,Linux下还有dump和restore这一对儿备份还原工具能够提供对文件进行打包和解包工作。此外,还有一个比较重要的工具cpio,它主要是用来备份任何东西的,也能够实现对文件的打包。当然,更为重要的是Linux系统的启动初始化镜像文件initrd是使用cpio制作的。cpio还是一个十分特别的程序,即它所打包的文件名不是利用命令选项提供的,而是通过标准输入传递的。而且它最终产生的打包文件也不是直接输出到磁盘,而是输出到标准输出中。为了能够使用cpio来完成为文件打包的工作,所以经常采用类似这样的命令:

$ find … | cpio -ocB > filename

在解包的时候cpio也不是直接读取打包文件,也是从标准输入中读入数据,所以要使用cpio解包,需要使用类似这样的命令:

$ cpio -idc < filename

上述的find命令怎么用和cpio的命令行选项都有什么含义,利用Linux的联机帮助手册都能够查到,只是这其中的一些特殊符号,比如:“|”、“>”和“<”却很难找到合适的说明。它们是什么呢?与Linux下的程序执行有关。所以,为了能够真正了解cpio的工作方式,还需要继续下面的内容……



[1]有关环境变的内容我们将在后面的章节做介绍。

[2]传统UNIX风格的命令行选项使用单个字母,这样多个选项进行组合时,可以剩下分隔符。

[3]你可以参考第一种形式推理为什么选项f一定要放在最后,如果实在想不出,可以发邮件给我。

热点排行