BBS水木清华站∶精华区

发信人: ruster (尘埃*星辰*领悟), 信区: Linux        
标  题: 第二章 Linux基础(上) 
发信站: BBS 水木清华站 (Thu Dec 21 13:26:00 2000) 
 
 
第2章 Linux基础 
   
  本章要点: 
   
  本章介绍Linux的一些基本概念,特别是文件系统和进程管理的基本知识。 
   
      本章具体包括以下内容。 
   
    LINUX文件系统概述 
   
    系统内核概述 
   
    shell脚本的基本格式 
   
    UNIX的用户权限和用户账号管理 
   
    进程管理的基本概念和操作 
   
    Linux的发行版本 
   
  2.1 文件系统 
   
  让我们首先来解释Linux的文件系统概念。我无意将你培养成为职业的系统破坏者,只 
是介绍一些基本概念。特别地,直接操作设备的物理扇区来读写ext2文件系统这样的想 
法让我只要想一下就会脖子发凉,如果你是这方面的专家,请告诉我到底怎么做。 
   
  2.1.1 UNIX和树状文件系统 
 
   
  与普通的UNIX系统一样,Linux使用树状的文件系统。每个系统都有一个根目录,从这 
里开始可以遍历整个系统中的所有文件,它没有驱动器和盘符的概念。 
   
  你可能会怀疑在没有驱动器符的情况下Linux如何处理多于一个的磁盘分区,可以看一 
下下面的示意图: 
   
  
   
  图2.1 文件系统示例 
   
  在我们的例子里,在/下有四个目录,其中,/bin直接和/位于同一个分区中,这个包 
含/的分区称为根分区。除此之外,根分区下还存在三个目录:/home,/mnt和/usr。 
   
  在系统中要存放大量的常用文件,例如日常的命令,系统文档等等。我们分划了一个 
独立的分区用来存放这些文件,这个分区被“连接”在/usr目录下,因此要访问分区上 
的文件只要访问/usr目录就可以了。 
   
  同样,我们为用户的私人文件开设了一个分区,连接在/home下面,每个用户都可以使 
用自己的目录内的文件(比如:/home/emp1)。但是我们发现有一个目录需要容纳特别 
多的文件,以至于将它单独分区可能会好一些,因此我们又设置了一个独立的磁盘用来 
容纳这些数据,这个磁盘分区被连接到/home/httpd。 
   
  这台机器上还包含了一个DOS分区,一个光盘驱动器,另外网络中还有一个服务器提供 
了共享的网络目录,我们把它们全都连接到文件系统之中,不过由于每个目录分支点( 
术语叫mount point)只能安装一个文件系统,所以我们在/mnt下面开设了三个目录来连 
接它们。 
   
  所有的文件都可以通过目录名加文件名来访问,对于系统来说,具体的每个文件到底 
在那个磁盘或者那个服务器上是无关紧要的,只要了解这个文件所在的目录就行了。Li 
nux利用/作为根目录的标志以及目录层之间的分割符,其作用相当于DOS的\。不过与DO 
S不同的是,Linux的文件名、目录名命名规则要宽泛的多,可以用相当长的文件名和目 
录名,在文件名和目录名中都可以包含不止一个的句点,而且区分大小写。例如 \test 
和\TEST是不同的两个文件。而一个位于/mnt/dos目录下的名为file1的文件其绝对路径 
名就是/mnt/dos/file1。 
   
  应该指出的是,“文件系统”这个词在Linux文献中有几种含义,第一种用来描述我们 
这里说的从/开始的系统中所有文件和目录的集合;第二种用来描述如同我们例子里面与 
/usr对应的那个分区那样的可以直接连接到某个目录下的完整集合体,即文件系统的一 
个独立部分;第三种含义是文件系统的具体实现方式,即操作系统如何把这种逻辑的目 
录结构映射成磁盘上的数据。具体的含义很容易根据上下文判断出来,大家可以自己注 
意。 
   
  用cd命令可以在不同的目录之间切换,Linux承认绝对路径和相对路径,这个内容对于 
任何熟悉dos的用户都应该是极其简单的,例如从/mnt/dos切换当前路径到/home/httpd 
的命令可以是cd /home/httpd,也可以是cd ../../home/httpd。但是必须注意的是,在 
cd命令之后的空格不可省略。 
   
  尽管理论上Linux应该自动对文件名进行过滤,但是这方面仍然有一些问题,例如,L 
inux允许用减号作为一个文件的起始字母,然而-也用于许多命令后的开关,因此会带来 
一些问题,如果你碰到了类似的问题,有时候使用绝对路径名会解决问题。 
 
   
  2.1.2 文件类型和文件组织 
 
   
  Linux把许多不同的东西看成文件。在一般情况下,我们会碰到下面类型的文件: 
   
  普通文件 
   
  目录 
   
  设备文件 
   
  链接 
   
  普通文件和目录 
   
  普通文件和目录的含义与DOS或者windows下的概念是类似的,普通文件就是一些数据 
的集合,而目录则是包含文件的容器。实际上,目录也是一种特殊的文件,只是它包含 
的内容是文件的存放信息。文件可以用rm命令删除,目录用mkdir命令建立,用rmdir删 
除。 
   
  设备文件 
   
  UNIX设备被当成文件来处理,通常UNIX的设备文件被分成字符设备和块设备,字符设 
备通常是类似于终端那样可以用处理文本文件的方式来处理的东西,例如,Linux在启动 
时打开了六个虚拟终端,分别称为tty1到tty6,这些虚拟终端对应的文件是/dev/tty1到 
/dev/tty6。假设你有超级用户权限,就可以直接向这些TTY上写文本,而这些文本则会 
显示在主机的控制台上。块设备则代表了类似磁盘的东西,如磁盘,CD-ROM或者虚拟驱 
动器。一般情况下,每个块设备还要包含一些子设备,例如,第一个IDE硬盘被称为hda 
,但是这个硬盘可以包含多个分区,那么,第一个分区称为hda1,以下依次是hda2,hda 
3,….等等。 
   
  设备文件用mknod命令建立,用rm命令删除。 
   
  链接 
   
  链接实际是一种文件别名,每个文件至少应该有一个名字,而如果你需要给文件增加 
一个名字以便访问,那么就需要建立一个链接。链接被分为软链接和硬链接。软链接实 
际上只是一段文字,里面包含着它所指向的文件的名字,系统看到软链接后自动跳到对 
应的文件位置处进行处理;相反,硬联接为文件开设一个新的目录项,硬链接与文件原 
有的名字是平权的,在Linux看来它们是等价的。由于这个原因,硬链接不能连接两个不 
同文件系统上的文件。 
   
   链接可以用ln命令创建,例如,在/home/user目录下有一个文件dest,现在需要在/ 
tmp目录下建立一个链接以便直接在/tmp下访问它,那么可以用这样的命令: 
   
  ln /home/user/dest /tmp/dest 
   
  这个操作将会建立一个硬链接,但如果/home/user和/tmp在不同分区上时这个命令将 
会失败。 
   
   ln –s /home/user /tmp/dest 
   
  这个命令将建立一个软链接。 
 
   
   如同其它UNIX Like系统一样,Linux的目录组织经常给人晕头转向的感觉,下面是一 
些基本的目录的说明。注意,理论上你可以更改这些目录的位置和名字,但是这样做很 
可能使一些假定文件“就在哪里”的程序混乱。 
   
    /:所有目录的“祖先”。 
   
   /lib:大部分应用程序必须使用的动态连结库文件 
   
   /usr:绝大部分的东西都在那里,比较复杂的应用程序(/usr/bin,/usr/sbin), 
应用程序的附加文件(/usr/lib),应用程序的文档(/usr/doc),应用程序的联机手册 
(/usr/man)。 
   
  /usr/local:这里是一般的附加软件的安装地点,如果你在安装了Linux之后又试图安 
装新的应用程序包,通常会被安装在这里。 
   
   /var:这里包含的是一些随着系统运行会不断改变的内容,例如各种记账信息,邮件 
和打印队列等等。许多人建议把它单独构成一个分区。 
   
   /tmp:临时文件,有必要的话将它独立成一个分区。 
   
   /dev:Linux用这个目录存放设备文件。 
   
   /proc:这实际上不是一个磁盘目录,而是用来显示系统的运行状态,在其中包含各 
种虚拟“文件”用来显示系统的当前状况,如进程和CPU等等。 
   
   /mnt:习惯上在这个目录下开设出各种文件系统的连结点,但你可以随便更改它而不 
会带来任何问题。 
   
   /home:缺省的非超级用户的宿主目录的所在地点。 
   
  2.1.3 使用文件系统 
   
  通常,对于服务器,我们在安装的同时就为它设计好了文件系统,特别是如何分区, 
某个分区应该连结到哪个目录下等等。但是我们也需要对文件系统进行维护,例如为服 
务器增加一个硬盘,或者解决文件系统混乱的灾难性问题等等。另外,诸如CD-ROM,软 
磁盘,或者服务器上的共享目录等等显然是需要经常更换的,在Linux中,用文件系统的 
安装和拆卸来对付这样的问题。 
   
  本节不会涉及那些有关处理文件系统灾难或者建立新的分区之类的问题;这种问题可 
以参考系统配置和日常维护的那两章,这里只是介绍一些基本的知识。 
   
  一个文件系统可以连结到已有的Linux系统中,也可以把连结上的文件系统从整个目录 
树中脱离,这是用mount和umount命令实现的。 
   
  mount命令的格式是 
   
  mount 开关 分区或者设备名 文件系统连结点  
   
  开关是一些命令参数,例如,假定我们需要使用某个软盘上的文件,将它插入驱动器 
A,然后执行 
   
  mount /dev/fd0 /mnt/floppy 
   
  然后软盘的文件系统就被挂到/mnt/floppy目录下,相当于dos的a:\file1的文件现在 
的名字是/mnt/floppy/file1。注意mount命令要求在挂接之前连结点(在这个例子中是/ 
mnt/floppy)必须存在,否则无法执行。 
   
  一般总是把文件系统连结到某个空目录。假如/mnt/floppy目录在连结之前就包含某些 
文件,那么执行上述命令的结果将使/mnt/floppy目录的内容变为软磁盘上的内容,而原 
有的内容在卸掉这个文件系统之前将不可访问。 
   
  /dev/fd0是与驱动器A对应的设备,相应地驱动器B是/dev/fd1。硬盘的情况比较复杂 
,因为Linux是利用设备接口来描述设备的,例如,第一个IDE接口上的主盘是/dev/hda 
,从盘是/dev/hdb,第二个IDE接口上的两个盘是/dev/hdc和/dev/hdd。问题是由于硬盘 
使用的是分区,所以必须使用子设备名,例如,把/dev/hda上的第一个分区连结到/mnt 
/diskc上的命令是 
   
  mount /dev/hda1 /mnt/diskc 
   
  相应地,第二个分区是/dev/hda2,以此类推 
   
  同样,SCSI驱动器用/dev/sda,/dev/sdb等等描述,对应的子设备名字是/dev/sda1, 
/dev/sda2等等。 
   
   Linux对IDE光驱用硬盘的命名方式,不过光盘不存在分区问题,所以可以直接使用设 
备名,例如把第二IDE从盘上的CDROM连结到/mnt/cdrom的命令是 
   
   mount /dev/hdd /mnt/cdrom 
   
  mount命令最常用的两个命令开关是-t和-o ,-t命令用来标志准备挂接的文件系统的 
类型,(在下一小节中详细介绍),-o选项用来设置一些选项,最主要的选项是ro和rw 
。这两个选项定义了对文件系统的存取方式,如果使用ro选项,那么这个文件系统将以 
只读方式连入,无法修改上面的任何信息。缺省的设置是rw。 
   
  连结了一个文件系统之后,就可以向这个系统对应的目录进行操作,效果就是操作对 
应的文件系统,如果要把这个文件系统卸下,使用umount命令,其格式是: 
   
  umount 连结点 
   
  例如,在上面的例子中,把连结在/mnt/floppy的软盘文件系统卸下的命令是 
   
  umount /mnt/floppy 
   
  注意由于这个过程会改变目录结构,因此必须在没有任何进程访问/mnt/floppy下的文 
件,也没有任何用户的当前目录是/mnt/floppy或者它的下级目录时才能完成,否则会返 
回一个 device is busy的错误。在有些UNIX系统中你可以用umount –f 的方法来强行 
越过这个限制,但这是一种极其粗野的方式,只有你明确地知道你到底在干什么才可以 
,在Linux中这个功能已经被取消。(有一个有趣的问题,如果你的文件系统是级联的,那 
么在拆卸下级文件系统之前上一层文件系统不能被拆卸)由于这个原因,在有人使用系统 
的情况下拆卸服务器的文件系统几乎是不可能的。如果你实在要这样干,请参考系统配 
置那一章,将系统切换到单用户模式,这个过程会把所有用户从系统上踢掉,然后再完 
成你的拆卸过程。 
   
  作为一种保护机制,已经mount的cd-rom不能通过按下面板上的按钮直接弹出,而必须 
首先执行umount命令,当然也可以用eject命令完成umount和弹出的自动操作。对于软盘 
没有这样的保护,所以你必须注意不要弹出一个已经连结的软盘,如果你这么做了,由 
于unix的文件工作方式,除非这个软盘是以read only方式连入,否则几乎肯定会出现问 
题。 
   
  mount和umount都需要超级用户权限才能执行,另外,它们都支持-a选项,mount –a 
挂接在/etc/fstab中定义的所有可挂接文件系统;umount –a卸下所有定义在/etc/mta 
b中得已挂接文件系统。每当挂接一个文件系统时,系统自动在/etc/mtab中增加一条纪 
录;当这个系统被卸下时自动把纪录清除。直接输入不带参数的mount指令将会显示当前 
已挂接的文件系统。 
   
  2.1.4 VFS、缓冲和ext2 
   
  每一种UNIX变体都有其独特的文件系统实现方式,Linux文件系统的实现依赖于所谓e 
xt2文件系统,但是它也支持其他许多种出自其他操作系统的文件系统实现。在这个方面 
,Linux引入了虚拟文件系统(VFS)的概念,任何文件系统连接入Linux时都必须先经过 
VFS映射成为标准的文件系统。只要增加VFS到具体文件系统的映射,就可以让Linux支持 
新的文件系统。一般说Linux必须在ext2文件系统上启动,但是也存在用基于MSDOS的某 
种文件系统来实现它的可能。 
   
  VFS的最大一个影响也许是在缓冲文件方面。如同在MS-DOS上经常看到的那样,Linux 
也使用内存高速缓冲磁盘的读写。事实上,为了提高性能,Linux被设计为将“几乎所有 
”的空余内存都用来作为磁盘缓冲,这个设计使得Linux具有UNIX类系统中最高的磁盘效 
能。(如果你对这个有兴趣,那么,有些人曾经宣布,在Linux+PeniumII+IDE上运行ta 
r+zip比Sun solaris+SCSI上快一倍左右,原因是solaris不使用磁盘缓冲。)它的缓冲 
对读写都同样有效,为此,系统必须每隔一段时间将缓冲区中的内容和磁盘中的内容进 
行同步,如果在同步间隙中掉电,未写入的数据将会丢失。在拆卸任何文件系统或者关 
机、重新启动之前,系统内核将自动同步其内容。当然你也可以使用sync命令来进行这 
个同步。 
   
  尽管如此,仍然可能由于某些原因使得文件系统未能正确同步,通常造成这种现象的 
原因是掉电,因此,缺省的系统启动脚本会在每次重新启动时自动检测文件系统,并且 
启动fsck程序修理那些没有正确同步的文件系统。(fsck是系统管理员用来修理文件系 
统的主要工具,它的用法我们将在“日常维护”中介绍。)这个命令有时要耗费很长的 
时间。 
   
  Ext2是Linux的标准文件系统,与任何UNIX文件系统类似,它将磁盘分割成为一系列数 
据块,再由数据块构成块组。每个文件由唯一的I节点(inode)描述,它包含文件的存放 
和权限信息。象一切UNIX一样,Linux在内存中缓冲inode表来加快文件的存取。 
   
  (如果这些内容会让你糊涂,那么不要紧,你并不需要了解ext2的具体实现。实际上 
对于一个非内核设计者来说理解ext2的实现的唯一理由是要去挽救一个已经被灾难完全 
摧毁的文件系统。然而,备份和恢复会容易的多,不是吗?) 
   
  2.1.5 其它文件系统 
   
  Linux支持许多文件系统,“支持”的意思是说你可以把载有这些文件系统的磁盘分区 
或者什么其他的设备直接连接到Linux文件系统中。一般情况下,如果要连接一个不是e 
xt2的文件系统,你需要在mount命令行中用-t指令明确地给出文件系统的类型。Linux系 
统目前支持的文件系统类型主要有: 
   
  minix:最早的MINIX系统的文件系统 
   
  ext2:Linux的标准文件系统,它还有一个比较早的形式即ext,目前已经不用 
   
  msdos:这就是标准的MSDOS文件系统 
   
  umsdos:这是一个特殊的文件系统实现,可以用MSDOS来存贮类似UNIX的长文件名文件 
   
  vfat:这是windows 95/98使用的文件系统,支持windows 95长文件名 
   
  iso9660:CD-ROM的标准文件系统 
   
  hpfs:OS/2用的文件系统 
   
  ntfs:windows nt 4.0用的文件系统(使用它要小心,目前这个功能还不是很可靠, 
绝对不要把一个NTFS文件系统连接成rw的方式!) 
   
  ufs:BSD用的文件系统 
   
  sysv:System V系列的一些UNIX使用的文件系统。 
   
  Ext2和ISO9660通常不需要使用类型说明,而msdos/win95文件系统则常常需要明确地 
说明其为msdos或者vfat,例如,在/dev/hdb2上装有一个windows 95文件系统,那么, 
将它连结到/mnt/win95的命令是 
   
  mount /dev/hdb2 /mnt/win95 –t vfat  
   
  偶尔你必须为连结到文件系统中的msdos软盘说明其类型: 
   
  mount /dev/fd0 /mnt/floppy –t msdos 
 
   
  2.2 系统内核基础 
   
  下面我们要解释有关系统内核的一些东西。必须记住,GNU+Linux的一个特色是如此之 
多的程序可以使用,因此几乎所有的东西都可以用你自己的东西替换掉,除了系统内核 
。 
   
  2.2.1 什么是内核 
 
   
  Linux将系统的一些关键性程序分离出来构成所谓操作系统内核。象大部分UNIX操作系 
统的内核那样,Linux内核必须完成下面的一些任务: 
   
  管理对文件系统的读写,把对文件系统的操作映射成对磁盘或其他块设备的操作 
   
  管理程序的运行,为程序分配资源,并且处理程序之间的通讯 
   
  管理存储器,为程序分配内存,并且管理虚拟内存 
   
  管理输入输出,将设备映射成设备文件 
   
  管理网络 
   
  文件系统的概念我们已经在前面一节中介绍过了,内核必须包含VFS管理程序以及将各 
种具体文件系统映射成VFS的程序。另外的几项功能差不多也象文件系统一样复杂,首先 
是对于内存的管理。 
   
  Linux使用虚拟存储管理方式,利用现代处理器的页面映射能力,在x86处理器上,Li 
nux使用4GB地址空间,系统的物理存贮器通常总是少于这个数字。操作系统除了使用物 
理存储器外,也支持将硬盘空间映射成为虚拟内存。所有存贮器(物理内存和虚拟内存 
)分成大小相等的页面,在x86系统中,每一页的大小是4kB,通过给出页号和页面内偏 
移量对某个内存地址进行访问,在物理内存紧张的时候,操作系统必须把某些没有使用 
的页面从内存移动到硬盘上以便腾出空闲的页面供程序使用,这个过程称为对换。 
   
  显然对换需要虚拟存储空间,通常情况下Linux用交换分区来处理这个问题,在硬盘上 
开设一个独立的分区专门用于映射虚拟内存,这种分区称为交换分区。交换分区可以并 
且经常不止一个,之所以这样是由于早期的Linux核心要求每个交换分区不能超过128MB 
。对于较重负荷的服务器,交换内存用到256MB甚至更多都是很正常的事情,因此那时的 
系统经常有多个交换分区,目前这个限制已经去除,但仍有人使用多于一个的交换分区 
。 
   
  核心的另外一个任务是执行用户程序,为此核心必须支持可执行文件格式。Linux使用 
多种可执行文件的格式,诸如elf,a.out等等(与ms-dos不同,没有办法从名字上区分 
一个文件到底是什么格式,核心只关心二进制文件的具体形式)。 
   
  除此之外,所有的设备驱动程序都必须包含在系统内核之中,依靠这些驱动程序操作 
系统才能够对硬件进行操作。 
   
  2.2.2 可加载模块和设备驱动程序 
   
  在一些系统中内核的运行参数以及内核中包含的设备驱动程序都只能在系统启动时装 
入,因此要想改变系统硬件或者对硬件的运行参数进行调整,唯一的选择是重新启动。 
Linux支持在运行期间加载核心模块。 
   
  模块(modules)是Linux的概念,它意味着可以将一些功能的程序分离出来,动态地加 
入和撤出内核。通常这种实现的目的是减少内核需要的物理存储空间(内核不能对换, 
也不使用虚拟内存映射)以及使系统的配置更灵活。尽管理论上随意加入和拆卸内核的 
功能容易使内核陷入危险中,但是Linux的实现使得加载一个内核模块实际是相当安全的 
。 
   
  必须注意的是,一个放在模块中的程序和直接放在内核映像文件(例如,在许多系统 
上的/vmlinuz)中的并没有什么不同,把某个部分当成模块还是直接放入内核映像的理 
由通常只是为了方便。例如,尽管可以把软驱的驱动程序作成可加载模块,但是对于一 
个经常使用软盘的用户来说这只会带来烦恼,因为在使用软盘之前他必须将驱动模块调 
入,相反,对于一个普通用户,ntfs驱动程序可以合情合理地做成模块,因为需要访问 
windows NT分区的几率肯定是很小的。网卡和声卡驱动程序也通常做成模块的形式,因 
为它们的种类实在太多,在内核中包含所有的驱动程序肯定是一种疯狂的想法。 
   
  内核模块可以用insmod命令加载,用rmmod命令卸载,其语法是: 
   
  /sbin/insmod 模块名 
   
  /sbin/rmmod 模块名 
   
  而使用lsmod命令可以显示当前加入的内核模块。 
   
  由于许多模块的加载都涉及到复杂的版本、相互依赖等问题,所以Linux文档提倡使用 
更简单的modprobe命令来加载模块: 
   
  /sbin/modprobe 模块名 
   
  需要指出的是,模块是在编译系统内核时设定的,通常在/lib/modules目录下有一个 
目录,其名字是你的内核版本号(比如:2.2,14),而各种模块都包含在这个目录下, 
名字是xxxx.o,xxxx是模块名,而.o是缺省的扩展名。在使用上面的各个命令时,不需 
要使用扩展名也不需要使用路径。例如,使用/lib/modules/2.2.14/ipv4/ip_masq_qua 
ke.o的命令为 
   
  /sbin/modprobe ip_masq_quake.o 
   
  也存在另外一种方案,这种方式中,当核心需要某个模块时,它自动去寻找对应的模 
块文件并且将它加载到系统中。这是通过正确地编译内核实现的,不过,一般不推荐使 
用这样的办法,因为增大了出现意外事故的几率。 
   
  2.2.3 内核不做什么 
   
  Linux内核是一个比较复杂的程序,技术上讲,它不同于一些现代操作系统所采用的微 
内核,相反,许许多多的东西被加入到了内核之中。但是,比起许多其他系统,Linux内 
核是非常小而且简单的。另外,许多东西虽然是Linux的一部分但是和内核完全无关,拆 
卸它们至少在理论上不会影响系统的正常运转。 
   
  首先的可以拆卸或者替换的东西是命令解释程序,再就是X-Window,这些东西只是几 
个应用程序,它们并不运行在核心态中,对于Linux它们也不是绝对必要的(然而,这种 
说法也许只有理论上的意义,一个没有shell的Linux几乎肯定是不可操作的)。 
   
  2.3 shell和配置程序 
   
  作为一个UNIX系统管理者,你必须了解shell。Linux在对shell的依赖方面比其它UNI 
X产品好一些,因为有近乎无穷多的shell和相关的自动化工具可用。不过,我想无论如 
何,你都必须了解bash,这是Linux的缺省shell。 
   
  2.3.1 命令解释程序 
   
  一个复杂的可以编程的命令解释程序是UNIX的特色之一,它们通常被称为shell。由于 
shell仅仅是一些标准的UNIX程序,因此它可以毫无困难地在Linux上实现。当然一般人 
总是喜欢使用较为好用的shell程序。 
   
  Linux下用的最多的shell是bash,它很庞大也很复杂,但是确实功能强大。对于许多 
用户来说,bash的命令行接口已经足够好,例如提供了在命令行编辑历史纪录的功能。 
事实上,shell的用法可以用一本书来描述,因为shell命令本身构成了一种语言,具有 
不逊于一般语言的编程能力。 
   
  本书作者不奢望你是一个shell script专家,也无意让你成为一个shell专家,但是为 
了对系统进行有效的管理,至少必须能够看懂shell脚本。如果你已经熟悉shell编程就 
可以简单地跳过这一小节,否则,这里给出了对shell语法的一些简单描述。 
   
  一个shell脚本通常就是一个文本文件,但是被设置成具有可执行的属性。你可以合情 
合理的把它看成一个批处理命令,然而,shell允许使用变量和流程控制,因此它能完成 
的东西比DOS的批命令要丰富的多。 
   
  在shell脚本里面可以简单地定义变量,变量可以是一个数值或者字符串,shell并不 
了解变量类型的概念,区分变量类型的工作要你自己完成。 
   
  为了定义变量,可以简单地使用赋值语句,例如,下面的命令将my_var的内容置为1: 
   
  [wanghy@openlab wanghy]$ my_var=1 
   
  注意[wanghy@openlab wanghy]$是系统提示符。后面的才是输入内容。在使用bash时 
有一个特殊要求,即等号两边不能有空格。 
   
  如果要访问变量的内容,使用$前缀,例如: 
   
  [wanghy@openlab wanghy]$ echo $my_var 
   
  1                                  
   
  另外,Linux定义了一些特殊的变量,首先是命令行参数,这些参数被用$0,$1,…的方 
式引用,$#则指代命令行参数的个数,$*则给出全部参数构成的字符串。如果这些说法 
让你感到困难,看一下下面脚本的运行结果。 
   
  [wanghy@openlab wanghy]$ cat testpar 
   
  echo $0 
   
  echo $1 
   
  echo $2 
   
  echo $* 
   
  [wanghy@openlab wanghy]$ ./testpar par1 par2 par3 
   
  ./testpar 
   
  par1 
   
  par2 
   
  par1 par2 par3                       
   
  shell中定义了一些特殊的字符,除了$指代变量,<,>,<<,>>,|进行标准I/O重定向之外 
,还有下面一些字符: 
   
  `  这个符号(就是在Tab和Esc之间的那个键)用于执行命令替换,例如出于某种原因 
你想执行uname –r命令得到内核的版本号并且存入$kernel_version里,可以执行下面 
的程序代码: 
   
  kernel_version=`uname -r` 
   
  双引号和单引号用于标记字符串,但是它们也有一些不同,主要是如果有一个字符串 
中包含$var这样看起来象是变量名的部分时,双引号括起来的字符串将其解释为变量而 
单引号不作任何处理。 
   
  反斜杠用于在字符串中包含特殊字符。 
   
  . 号用于执行一个脚本,例如:. ./testpar执行当前目录下的testpar脚本。它不能 
用于执行二进制文件。 
   
  Bash的另外一个功能是执行各种程序流程,它支持if….then….else…..fi的选择模 
式,其中if后跟各种测试指令,测试指令的基本形式是test 表达式,如test 1<2,tes 
t –f /etc/smb.conf等等。test也可以用方括号代替,例如test 1<2 和[ 1 < 2 ]等价 
,注意使用方括号时方括号和中间的表达式之间必须用空格隔开。可以选择的测试指令 
包括: 
   
  数字比较 
   
  -eq (等于) -ge (大于等于)-le(小于等于)-ne(不等于)-gt (大于)-lt(小 
于) 
   
  字符串比较  
   
  = 等于 != 不等于 –n 字符串长度是否大于零 –z 字符串长度是否等于零 
   
  文件测试 
   
  -d 是否为目录 
   
  -f 是否存在这个文件 
   
  -r 是否可读 
   
  -s 是否具有大于零的长度 
   
  -w 是否可写 
   
  -x 是否可执行 
   
  逻辑操作 
   
  ! 求逻辑非 
   
  -a 逻辑AND 
   
  -o 逻辑OR 
   
  另外,shell支持for,while,until和case,shift语句。if,while,case和until语 
句的用法都很简单,只要看一下系统给的例子就可以了,for语句比较复杂,其格式是 
   
  for var in list 
   
  do 
   
   ….. 
   
   done 
   
  其含义是对list中的每个值执行一次循环。如果list写成”$@”则对所有命令行参数 
执行一次循环。 
   
  下面是case的基本用法: 
   
  case str in  
   
  str1|str2) 
   
  statement1; 
   
  str3|str4) 
   
   statement2; 
   
  str5) 
   
   statement3; 
   
  *); 
   
  esac 
 
   
  *相当于"case else"。str1|str2)表示“若等于str1或者str2则” ,小括号是不可少 
的。 
   
  while语句的用法是 
   
  while   { expression } 
   
  do  
   
  ..... 
   
  ...... 
   
  done 
   
  until语句的用法是 
   
  until test expression 
   
  do 
   
  ....... 
   
  ...... 
   
  done  
   
  shift语句与dos里的用法相同,它把命令行参数的位置左移,缺省的情况下移动一次 
。 
   
  另外的标准语句还有break和exit,分别用于退出一个循环或者退出当前脚本。 
   
  还有一个语句是select,用来接受用户输入,其用法可以参考下面的脚本: 
   
  select input in continue over 
   
  do 
   
  if test $input = "continue" ; then 
   
  echo "contiune" 
   
  else 
   
  echo "over" 
   
  exit 
   
  fi 
   
  done         
   
  [由于本书仅仅希望你能够看懂script而不是会编写复杂的script,因此不准备详细地 
叙述shell编程的要点。当然许多人把会熟练地编写script看成一个UNIX高级用户的标志 
,但是对于Linux系统管理员来说,高超的脚本技能绝对不是必要的。] 
   
  2.3.2 不同的shell 
   
  对于大部分人来说,UNIX提供的shell是太多了,最常用的大概是sh,csh和bash程序 
,但是其他的象tcsh,zsh之类的程序也经常出现,如果有兴趣,你可以看看在Linux发 
行盘里面提供了多少种不同的shell。问题在于,不同的shell不仅是外貌不同,在流程 
控制和表达式的使用方面也存在区别,事实上,这样的问题经常让人晕头转向。 
   
   在Linux的启动阶段,它使用sh作为命令解释器,其语法就是我们刚才讨论的语法, 
但是不支持bash提供的一些高级特性。事实上,bash是作为对sh程序的一种强化出现的 
。当Linux准备就绪以后,它使用/etc/passwd文件中的描述为每个用户提供自己的shel 
l,通常提供的是bash或者csh。这些shell都是用户友好的,提供了诸如命令行补齐,历 
史纪录,通配符等等高级特性。不过,许多人都喜欢使用自己习惯的shell程序。 
   
   对shell掌握程度曾经是UNIX用户水平的衡量标志之一,因为那个时候除了shell以外 
没有更好的自动化任务工具,有些系统甚至不愿意提供C编译器。但是现在,在perl和C 
编译器作为Linux发行版本的一部分出现时,过分的强调诸如shell,awk等工具的使用能 
力并无意义。作者建议你用Perl完成日常的任务管理工作。 
   
  2.3.3 配置程序、文档和编辑器 
   
  UNIX的一个典型的特性是它的系统配置程序都是文本。系统内核、应用程序等等都需 
要一系列数据进行缺省设置,在许多系统上,这种设置是以某种内部数据库的形式提供 
的,而在UNIX系统中,它们被实现为简单的文本文件。理论上,使用文本文件会使得配 
置文件的大小比压缩二进制编码大一些,但是文本文件容易操作的优点完全抵销了这个 
弱点。 
   
  传统上,系统的配置文件被放在/etc下面,一般情况下,如果要修改某个软件的设置 
,你需要做的就是编辑对应的配置文件,然后重新运行这个软件。Linux下的软件的配置 
文件被设置为很容易理解的形式(当然也有一些东西例外,比如sendmail)。一个典型 
的例子是缺省的/etc/bashrc,它用来设置一些bash使用的参数文件: 
   
  # /etc/bashrc 
 
   
  # System wide functions and aliases 
   
  # Environment stuff goes in /etc/profile 
 
   
  # For some unknown reason bash refuses to inherit 
   
  # PS1 in some circumstances that I can't figure out. 
   
  # Putting PS1 here ensures that it gets loaded every time. 
   
  PS1="[\u@\h \W]\\$ "                  
   
  以#开头的行很容易看出是注释行(大部分UNIX应用程序都这样,偶尔某些东西使用分 
号作为注释开始的标志)。所以实际的命令只有一行,如果你熟悉UNIX里面“说话的规 
则),你很容易看出这是用来设置缺省的命令提示符的(\u:用户名 \h:机器名 \W 目 
录名)。 
   
  对于UNIX专家来说,这种配置程序是极其简单的,只要一个普通的文本编辑程序就可 
以完成包括裁剪内核,调整软件运行参数等等多方面的工作,但是这也足以让新手晕头 
转向,尤其是当某些东西没有写在文档里面的时候。(有一个说法,当你不会使用某个 
软件时,windows用户决定去寻找一个更简单的产品,UNIX用户则去寻找一本更厚的文档 
)。Linux则采取了比较温和的办法,对于许多涉及到太多的配置文件的一些软件的设置 
,Linux提供许多配置程序(技术上这种东西可以在任何UNIX体系上使用,不过UNIX老手 
往往不屑于使用这种功能)。不过要记住,这些配置程序所作的和一个熟练的系统管理 
员用编辑程序作的实际是一样的(也许更愚蠢一些),只要你愿意,你总可以手工完成 
它的任何工作。不过,有些编辑工作是如此地复杂以至于除了它的开发者以外没有人愿 
意手工去做(比如说:sendmail)。相反,有些配置工具十分愚蠢,它们偶尔会给你带 
来一些严重的麻烦,所以有经验的用户决不用它。 
   
  这种文本编辑方式的系统配置显然要依赖于两种东西,文本编辑器和对于配置文件格 
式说明的文档。通常人们只是在已有的内容上面修改一下,因此通常各种Linux软件都提 
供配置文件的范例。但是更详细的内容必须通过文档来得到,Linux软件通常提供两种文 
档,即联机手册和文档文件。 
   
  联机手册是Linux文档的主要来源,一般它提供给那些“原生”的Linux程序,它有终 
端和X两种版本,例如,在终端下想要了解more命令的用法,输入man more就会出现类似 
下面的屏幕: 
   
  [root@openlab joe]# man more 
   
  MORE(1)                      UNIX Reference Manual                     MOR 
E(1) 
   
  NAME 
   
       more - file perusal filter for crt viewing 
   
  SYNOPSIS 
   
       more [-dlfpcsu] [-num] [+/ pattern] [+ linenum] [file ...] 
   
  DESCRIPTION 
   
       More is a filter for paging through text one screenful at a time.  Th 
is 
   
       version is especially primitve.  Users should realize that less(1) pr 
o?     vides more(1) emulation and extensive enhancements. 
   
  OPTIONS 
   
       Command line options are described below.  Options are also taken fro 

   
       the environment variable MORE (make sure to precede them with a dash 
   
       (``-'')) but command line options will override them. 
   
       -num  This option specifies an integer which is the screen size (in 
   
             lines). 
 
   
  :                                              
   
  注意结束处的冒号,这表示手册中关于more的内容还没有全部显示出来,用^F和^B可 
以上下翻页,当移动到手册页面末尾时,<end>标志将会出现。 
   
  阅读完毕之后,用q键退出。 
   
  在X下,执行xman  &就可以阅读手册内容。 
   
  偶尔某些名字有多重含义,例如exit既可能指shell的exit命令也可能指标准C的exit 
()函数,手册用分节的方式来处理这个问题,例如第一节是普通命令,第二节是标准系 
统调用等等,详细的定义可以在xman的菜单里面找到。要在终端下使用分节,使用 
   
  man –S [节号] 命令名 
   
  联机手册的内容构造的相当简明而清晰,但是对于一个新手来说,它们往往帮不上忙 
。许多软件在/usr/doc目录下提供了TXT或者HTML格式的较为详细的文档可以阅读。另外 
,/usr/doc/HOWTO目录中存放着Linux-HOWTO的内容,对于新手是最有用的信息来源之一 
。 
   
  如果你能够理解文档,那么就可以通过编辑配置程序来完成系统和应用软件的配置。 
这意味着你需要至少掌握一种编辑工具。UNIX下最主要的编辑工具是vi和emacs,但是对 
于象编辑配置文件这样的工作,它们的功能是过于强大了。如果你会用任何一种当然很 
好,如果你不会也无关紧要,象joe之类的编辑器要简单的多,而且同样可以完成工作。 
(个别发行商不提供joe,但这总不能妨碍你自己去下载源代码然后编译)。 
   
  2.3.4 定制环境 
   
  通常一个用户总是希望定制自己的shell环境。对于一个系统管理员来说,正确的系统 
设置可以加快工作的效率。 
   
  首先需要设置的是系统的预定义搜索路径。与MS-DOS不同,Linux只搜索在PATH环境变 
量里面明确地设置的路径,它并不执行对当前目录的搜索。因此,如果要执行当前目录 
里的程序,必须明确地用./指定: 
   
  ./test 
   
  设置路径的命令在各种shell里是不同的,在bash里,你需要的是定义一个PATH变量, 
然后把它输出到环境变量里面,这是通过export命令实现的: 
   
   PATH="/usr/bin:/bin";export PATH 
   
  用分号连结起来的两个命令连续地被执行,在export后面的PATH不用加$,设置路径时 
不同的目录之间用分号分开。当然,你也可以用两条命令来处理: 
   
  PATH="/usr/bin:/bin" 
   
  export PATH 
   
  另外一个很多人喜欢定制的环境变量是提示符,bash用PS1和PS2来设置提示符,这表 
示shell的一级提示符和二级提示符。例如,下面的命令把提示符设置成为MS-DOS方式: 
   
  PS1="\w>";export PS1 
   
  \w代表当前工作目录,类似的特殊字符还有 
   
  \#       显示当前命令的命令编号。  
   
  \$       显示$符作为提示符,如果用户是root的话,则显示#号。  
   
  \\       显示反斜杠。  
   
  \d       显示当前日期。  
   
  \h       显示主机名。  
   
  \n       打印新行。  
   
  \nnn     显示nnn的八进制值。  
   
  \s       显示当前运行的shell的名字。  
   
  \t       显示当前时间。  
   
  \u       显示当前用户的用户名。  
   
  \W       显示当前工作目录的名字。  
   
  \w       显示当前工作目录的路径。  
   
  另外一种十分有用的技术是别名。别名用alias命令实现,例如 
   
  alias ll="ls -l" 
   
  以后输入ll就等效于输入ls –l。 
   
  有几个缺省的别名,如果你的系统没有设置,强烈建议你加上,即 
   
  alias rm="rm –i" 
   
  alias cp="cp –r" 
   
  alias mv="mv –r" 
   
  这几条命令可以提供对错误操作的一种预防方式。 
   
  你可以对自己的shell加上复杂的定义,但是当你退出系统时,这些定义就消失了,为 
了使这些定制信息自动可用,可以有多种处理方法。最简单的是在你的宿主目录(/etc 
/passwd里面定义的你的主目录)中建立一个.bashrc或者.bash_profile文件(两个名字 
都可以),放入你想要定制的内容。以后bash开始执行时会自动去调用其中的内容。如 
果你用的是其他的某种shell,也有相应的配置文件,比如csh的配置文件是.cshrc。注 
意点号开始的文件名是隐含文件,只有用ls –a命令才能看到。如果你想要让所有用户 
都能自动使用这些东西,为他们建立一组合适的配置文件,然后拷贝到/etc/skel目录。 
   
   
 
 
-- 
当我越过无尽虚空的时候,我看见星辰的欲望,光荣和毁灭,这是光辉世界的宿命, 
一切的一切,最终必将落入黑暗和虚无。 
所以,我随着星光飞翔,去逃脱必然的终结,也许有一天,我将回到世界的原初, 
等待新的星辰的诞生。 
尘埃是星的起源,星的终结。 
 
 
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.112.90.20] 

BBS水木清华站∶精华区