在书写正确脚本前,大概讲一下退出状态。任何命令进行时都将返回一个退出状态。如
果要观察其退出状态,使用最后状态命令: $ echo $? 主要有4种退出状态。前面已经讲到了两种,即最后命令退出状态$ ?和控制次序命令( $ $、 | |)。其余两种是处理s h e l l脚本或s h e l l退出及相应退出状态或函数返回码。在第1 9章讲到函数 时,也将提到其返回码。 要退出当前进程,s h e l l提供命令e x i t,一般格式为: exit n 其中,n为一数字。 如果只在命令提示符下键入e x i t,假定没有在当前状态创建另一个s h e l l,将退出当前s h e l l。 如果在脚本中键入e x i t,s h e l l将试图(通常是这样)返回上一个命令返回值。有许多退出脚本 值,但其中相对于脚本和一般系统命令最重要的有两种,即: 退出状态0 退出成功,无错误。 退出状态1 退出失败,某处有错误。 可以在s h e l l脚本中加入自己的退出状态(它将退出脚本)。本书鼓励这样做,因为另一个 s h e l l脚本或返回函数可能要从s h e l l脚本中抽取退出脚本。另外,相信加入脚本本身的退出脚 本值是一种好的编程习惯。 如果愿意,用户可以在一个用户输入错误后或一个不可覆盖错误后或正常地处理结束后退出脚本。
s h e l l会提供一系列命令声明语句等补救措施来帮助你在命令成功或失败时,或需要处
理一个命令清单时采取正确的动作。 这些命令语句大概分两类: 循环和流控制。i f、t h e n、e l s e语句提供条件测试。测试可以基于各种条件。例如文件的权限、长度、数
值或字符串的比较。这些测试返回值或者为真( 0),或者为假( 1)。基于此结果,可以进行 相关操作。在讲到条件测试时已经涉及了一些测试语法。 c a s e语句允许匹配模式、单词或值。一旦模式或值匹配,就可以基于这个匹配条件作其他 声明。循环或跳转是一系列命令的重复执行过程,本书提到了3种循环语句:
for 循环每次处理依次列表内信息,直至循环耗尽。 Until 循环此循环语句不常使用, u n t i l循环直至条件为真。条件部分在循环末尾部分。 While 循环w h i l e循环当条件为真时,循环执行,条件部分在循环头。 流控制语句的任何循环均可嵌套使用,例如可以在一个f o r循环中嵌入另一个f o r循环。 现在开始讲解循环和控制流,并举一些脚本实例。 i f语句测试条件,测试条件返回真( 0)或假(1)后,可相应执行一系列语句。i f语句结 构对错误检查非常有用。其格式为: if 条件1 then 命令1 elif 条件2 then 命令2 else 命令3f i
让我们来具体讲解i f语句的各部分功能。 If 条件1 如果条件1为真 Then 那么 命令1 执行命令1 elif 条件2 如果条件1不成立 then 那么 命令2 执行命令2 else 如果条件1,2均不成立 命令3 那么执行命令3 fi 完成 i f语句必须以单词f i终止。在i f语句中漏写f i是最一般的错误。我自己有时也是这样。 e l i f和e l s e为可选项,如果语句中没有否则部分,那么就不需要e l i f和e l s e部分。I f语句可以 有许多e l i f部分。最常用的i f语句是if then fi结构。最普通的i f语句是:
i f条件 then 命令 f i 使用i f语句时,必须将t h e n部分放在新行,否则会产生错误。如果要不分行,必须使用命 令分隔符。本书其余部分将采取这种形式。现在简单i f语句变为: if 条件;t h e n 命令 f i[root@localhost huangcd]# sh iftest2
enter your name: your did not enter a information [root@localhost huangcd]# cat iftest2 #!/bin/bash echo -n "enter your name:" read NAME if [ "$NAME" = "" ];then echo "your did not enter a information" fi下面测试文件拷贝是否正常,如果c p命令并没有拷贝文件m y f i l e到m y f i l e . b a k,则打印错
误信息。注意错误信息中` basename $0`打印脚本名。 如果脚本错误退出,一个好习惯是显示脚本名并将之定向到标准错误中。用户应该知道 产生错误的脚本名。[root@localhost huangcd]# cat ifcp
#!/bin/bash if cp ok1.txt ok.bak;then echo "good copy" else echo "`basename $0`:error could not copy the files">&2 fi [root@localhost huangcd]# ./ifcp cp: 无法 stat “ok1.txt”: 没有那个文件或目录 ifcp:error could not copy the files
2代表标准出错,如果文件不存在,如果不加上2>&1则会打印出错信息,加上以后就不会打印了,也进入那个文件了&1代表标准输出定向到的地方,这句相当于cat cities > cities.copy 2> cities.copy或者cat cities 1> cities.copy 2> cities.copy或者cat cities 2> cities.copy 1> &20:标准输入,1:标准输出,2:标准出错
当运行一些管理脚本时,可能要在根目录下运行它,特别是移动某种全局文件或进行权
限改变时。一个简单的测试可以获知是否运行在根目录下。下面脚本中变量D I R E C TO RY使用 当前目录的命令替换操作,然后此变量值与" / "字符串比较( /为根目录)。如果变量值与字符 串不等,则用户退出脚本,退出状态为1意味错误信息产生。[root@localhost huangcd]# ./ifpwd
you need to be in the root directory.not /home/huangcd [root@localhost huangcd]# cat ifpwd #!/bin/bash DIRCTORY=`pwd` if [ "$DIRCTORY"!="/" ] then echo "you need to be in the root directory.not $DIRCTORY ">&2 exit 1 fii f语句可用来测试传入脚本中参数的个数。使用特定变量$ #,表示调用参数的个数。可以
测试所需参数个数与调用参数个数是否相等。 以下测试确保脚本有三个参数。如果没有,则返回一个可用信息到标准错误,然后代码 退出并显示退出状态。如果参数数目等于3,则显示所有参数。[root@localhost huangcd]# cat ifpatam
#!/bin/bash if [ $# -lt 3 ] then echo "Usage:`basename $0` arg1 arg2 arg3" >&2 exit 1 fi echo "arg1:$1" echo "arg2:$2" echo "arg3:$3" [root@localhost huangcd]# ./ifpatam cup medal Usage:ifpatam arg1 arg2 arg3 [root@localhost huangcd]# ./ifpatam cup medal thophy arg1:cup arg2:medal arg3:thophy下面的例子测试环境变量E D I TO R是否已设置。如果E D I TO R变量为空,将此信息通知用
户。如果已设置,在屏幕上显示编辑类型。[root@localhost huangcd]# cat ifeditor
#!/bin/bash if [-z $EDITORS ] then echo "your EDITOR environment is not set" else echo "Using $EDITOR as the fefault editor" fi [root@localhost huangcd]# ./ifeditor ./ifeditor: line 2: [-z: command not found Using as the fefault editor可以向脚本传递位置参数,然后测试变量。这里,如果用户在脚本名字后键入目录名,
脚本将重设$ 1特殊变量为一更有意义的名字。即D I R E C TO RY。这里需测试目录是否为空,如 果目录为空,ls -A将返回空,然后对此返回一信息。[root@localhost huangcd]# sh ifdirec
is indeed empty [root@localhost huangcd]# sh ifdirec /home /home is indeed empty [root@localhost huangcd]# cat ifdirec #!/bin/bash DIRECTORY=$1 if [ "`ls -A $DIRECTORY`"="" ] then echo "$DIRECTORY is indeed empty" else echo "$DIRECTORY is not empty" fi