订单查询 购书指南 购物车 收藏  
    首页 热点专题 精确搜索 精品推荐 俱乐部论坛 下载服务 走近科海 征稿专栏 新书预告 各地经销商 特价直销


第10章 学习Bash

10.2 BASH Shell

   
早年的Unix年代,发展者众多,shell依据发展者的不同有许多版本,例如常见的Bourne Shell(sh)、Sun中默认的C SHell、商业上常用的K Shell以及TCSH等,每种Shell都各有其特点。Linux使用的是Bourne Again SHell(简称 bash),这个Shell是Bourne Shell的增强版本,是基于GNU的架构下发展而来。
    在介绍shell的优点之前,先讲讲shell的简单历史。第一个流行的shell是由Steven Bourne开发出来的,为了纪念他所以称为Bourne shell,简称sh。后来另一个广为流传的shell是由柏克莱大学的Bill Joy设计的依附于BSD版的Unix系统中的shell,这个shell的语法有点类似C语言,所以得名为C shell,简称为csh。由于在学术界Sun主机势力相当庞大,而Sun主要是BSD的分支之一,所以C shell也是另一个很重要且流传很广的shell之一(因为太多的程序设计师使用的就是C语言)。
    BASH是GNU计划中重要的工具软件之一,目前也是GNU操作系统中标准的shell,它主要兼容于sh,并依据一些用户需求而加强,可以说目前几乎所有的Linux版本都是使用bash作为管理核心的主要shell。因此,不论您使用的是哪个版本,都必须学习bash。那么这个shell有什么好处,为什么Linux要使用它作为默认的shell呢?BASH主要的优点有下面几个。
    命令编辑能力(类似DOS的doskey功能)
    bash中个人认为相当棒的一个功能就是它能记忆使用过的指令,您只要在命令行中按上下键就可以找到输入的前一个指令。Mandrake 9.0默认的指令记忆功能可以到达1000个,也就是说,您曾经输入的指令都被记录下来,记录的文件在根目录的.bash_history下。
    不过,需要留意的是,~/.bash_history记录的是上一次登入以前执行过的指令,至于这一次登入执行的指令都被暂存在内存中,当您成功注销系统后,该指令记忆才会记录到.bash_history中。这有什么好处呢?最大的好处就是可以查询您曾经有过的动作,知道您的执行步骤,因此可以追踪您曾输入的指令,以备除错之用。但如此一来也有个烦恼,就是如果有黑客入侵,他只要翻查您曾经执行过的指令,而这些指令又跟系统有关(例如直接输入MySQL的密码),那么很容易就能破解您的Linux主机。所以,最好是减少记录的指令数。
    补全功能(比对数据正确性)
    这个功能也相当棒,主要分为指令补全与文件名称补全。
    指令补全:用在执行命令时不想按太多按键的时候。例如指令pcprofiledump够长,如果在输入pcprofile之后按下Tab键,bash马上会自动将后面的dump接上来。如果有重复的指令呢?按下两次Tab将会把所有重复的指令都列出来。这样,直接在提示符后连按两次Tab键,系统会将所有可以使用的指令都列出来。如果我想知道目前系统中所有以b开头的指令,那么按下b之后,连按两次Tab就可以了。
    文件名称补全:此外,如果您用vi读取某个文件,例如/etc/man.config,您可以在输入vi /etc/man.之后直接按下Tab键,那么该文件名称会被自动补全。这项功能对于文件名称或者指令名称的正确性方面帮助也很大。所以,有事没事,在bash shell下多按几次Tab键是一个不错的习惯。
    命令别名(alias)设定功能
    若要知道某个目录下的所有文件(包含隐藏文件)及所有的文件属性,必须输入ls -al这样的指令,这挺麻烦,更快的替代方法是用命令别名。例如我喜欢直接用lm这个自定义命令来取代上面的命令,也就是说,lm等于ls –al。要实现自定义命令可以使用alias,在命令行输入alias就可以知道当前的命令别名都有哪些。也可以直接输入下列命令来设定别名:
    alias lm='ls -al'
    作业控制、前景背景控制
    这部分我们在后面还会提到。使用前、背景控制可以让工作更顺利。作业控制的用途则更广,可以让我们随时将作业放到背景中执行,而不用怕不小心使用了Ctrl + C关掉该程序。此外,还可以在单一登入的环境中达到多任务的目的。
    Shell scripts的强大功能
    DOS中有将一堆指令写在一起的所谓的“批处理文档”,Linux下的shell scripts则具有更强大的功能,可以将您需要频繁输入的连续指令写成一个文件,该文件通过交互方式进行主机的检测工作。也可以藉由shell提供的环境变量及相关指令编写一个小型的程序语言,这样,以前在DOS下只有程序语言才能写的东西,在Linux下使用简单的shell scripts就可以完成。这部分在后续章节还会详细讲解。
    在了解了BASH的优点之后,我们来谈谈如何在Shell环境中输入指令。其实很简单,输入指令的方式为:
    [root@test /root]# command [-options] parameter1 parameter2 ...
    指令 选项 参数(1) 参数(2)
    1. command为指令的名称,例如变换路径的指令为cd
    2. 中括号[]并不存在于实际的指令中,在加入参数时,通常为“-”符号,
    有时候完整名称会输入“--”符号。例如ls --help
    3. parameter1 parameter2为依附在option之后的参数,或者是
    command的参数
    4. command, -options, parameter1这几项之间以空格分隔,
    不论空几格shell都视为一格
    5. 指令太长的时候,可以使用 \ 符号来跳转Enter,使指令连续到下一行
    实例:
    [root@test /root]# ls -al /root
    以ls列出/root目录中的隐藏文件与相关的属性参数
    [root@test /root]# ls –al /root \> /
    上面这两行实际上是一行指令,但是加上 \ 跳转符号后,指令可以连续到下一行。请注意,\字符之后直接按下enter就可以,不可在后面接空格符
    [root@test /root]# ls -al /root
    这个指令与第一个相同,空格符不论几个,仅视为一个来处理
    还有一个问题:Shell什么时候开始接管Linux主机?我们在后面会讲到开机流程,这里先跳过去,假设您的机器已经启动成功,主机进入等待用户登入的状态。当用户输入账号与密码,并且顺利通过之后,经过shell的环境变量文件读取功能,最后,用户进入自己的根目录,例如root的根目录在/root下,一般用户的根目录则在/etc/passwd文件中设定,此时主机已经启动了一个程序bash供您操作。

10.3 变量与变量的设定

    继续研究BASH之前,我们先来讨论变量,因为主机中有太多的数据需要存取,而这些数据都是一些服务必须的,例如mail的存取路径/var/spool/mail、默认的根目录/home/useraccount等。我们可以改变这些变量,但是如果该变量已直接深植于套件中,那么修改了某些参数之后,套件必须重新编译源代码。这样很麻烦,所以,就引出了变量。
    举个简单的例子,sendmail的smtp存放mail的路径经由/etc/profile中的 MAIL="/var/spool/mail/$USER" 设定,当我修改了上面这一路径,然后重新登入,我的邮件就可以存放到不同的路径,并且可以顺利地在Linux主机上收发。然而问题发生在pop3这个服务上,由于pop3的路径已经硬编码在源代码中,而且正是/var/spool/mail这个路径,也就是说,不论我怎么修改我的“变量”,pop3都不会改变,所以无法直接以pop3收信(例如,OutLook就不能工作了),会发生密码不接受的现象。
    此外,我们在执行程序的时候,系统怎么知道您的ls指令放在哪里?这是因为有PATH变量。系统通过这个变量中设定的路径依序寻找该指令系统,如果找不到,屏幕上会显示command not found字样。这些是系统默认的变量,还可以自定义变量,例如您要写一个大型的脚本(批处理文件)时,由于路径在脚本中出现多处,如果换了一台主机,就要修改脚本中的所有路径,后果不堪设想。这时如果使用变量,将变量的定义写在最前面,后面相关的路径名称都以变量取代,那么您只要修改一行就等于修改了整个脚本。所以,良好的程序设计师都会善用变量的定义(这部分我们在下面还会提到)。
    从原理上说,在Linux系统中,所有的执行线程都需要一个执行码,就如同上面提到的,您真正以shell跟Linux沟通,是在正确登入Linux之后。这时候您就有一个bash执行程序,真正经由bash跟系统沟通。在进入shell之前,也正如同上面提到的,由于系统需要一些变量来提供数据的存取(或者是一些环境的设定参数值,例如是否显示彩色等),所以就需要一些所谓的环境变量来读入系统中,这些环境变量包括PATH,HOME,MAIL,SHELL等,都很重要。为了与自定义变量区别开来,环境变量通常以大写字符来表示。
    说了那么久,到底什么是变量?简单地说,变量就是以一组文字或符号取代一些设定或一串数据,例如,VBird就是鸟哥,所以当您读取VBird的时候,系统自然知道是鸟哥。下面以PATH为例说明,如果您对相对路径与绝对路径还有点印象,那么应该知道要输入正确的指令,应该指定路径与文件名。例如,要输入ls指令,应该指定其路径为/bin/ls,可实际上为什么在任意路径下都可以执行ls而不需要指定路径呢?因为系统已经预设了一些搜寻路径(PATH),需要执行这些指令时,系统会依照该PATH的设定搜寻指令,这个PATH就是所谓的变量。显示变量要用到echo指令。