SA118翻译(12)

weixin_38062058 2003-01-10 10:15:41

第十三章 阅读shell脚本 翻译:hfzheng hfzheng@sohu.com 转载请保留此信息 基本的shell脚本 一个shell脚本是一个ASCII文件,包含了一系列的命令以及注释。 注释是文档中的文本,用来说明脚本的功能以及每一行脚本执行完后需要完成的功能,注释以#开头。 确定shell脚本类型 脚本最上面一行说明执行脚本的shell程序类型,例如,对于Bourn shell而言,第一行应该是: #!/bin/sh 内核使用#!来识别用来翻译脚本的程序。 备注:korn shell的第一行应该为#!/bin/ksh,c shell的第一行应该为#!/bin/csh。 不过,并不是所有的shell脚本使用最上面一行来识别shell程序。 一些脚本可以在最上面有一个基本的文本注释。和父shell同样的shell来执行该脚本。一些脚本可能在最上面没有注释。在这种情况下,则使用默认的shell程序来执行该脚本。 创建一个基本的shell脚本 创建一个基本的shell脚本使用以下步骤: 1、使用vi编辑器,创建一个文件,名为my.script,输入命令,后跟tab键,然后以#开头定义注释; 2、使文件可以执行,然后在命令行方式下输入该文件的命令。 $ vi my.script who # To view who is logged on the system. date # To view the current date and time ls -l # To view files in current directory :wq $ chmod 755 my.script $./my.script Bourne shell编程 用于管理Solaris操作环境的标准管理脚本是bourne shell脚本。 为了成功控制、修改操作环境的行为,系统管理员必须可以读、修改和定制这些不同的shell脚本文件。 通常,所有的Bourne shell脚本包括了一组UNIX命令、Bourne shell内建命令、编程结构和注释。 Bourne shell脚本 要能够阅读,更重要的是理解基本shell脚本的内容,必须能够: 1、能够理解参数如何传给脚本,通过使用特殊的称为位置变量的内建变量传递; 2、能够识别和分析简单的条件结构和流程控制; 特殊的shell内建变量 位置参数 特殊的shell内建变量称为位置参数,用于从命令行中传递参数给脚本。 在命令行方式下,跟在脚本名称后的用空格分割的每个单词,称为参数,这些参数在shell脚本中称为位置参数。 命令格式 scriptname argument1 argument2 argument3 ... 当脚本执行时,shell自动存储命令行中的第一个参数到位置参数$1中,第二个参数到位置参数$2中,第三个参数到位置参数#3中,依此类推。 重置一个位置参数 set命令用于重置位置参数。 下面示例描述如何使用set命令来设置位置参数。 首先执行带选项-m的who命令,查看输出: $ who -m user1 pts/5 Mar 13 11:43 (host1) $ 现在使用cat命令创建shell脚本,命名为my.script3: $ vi my.script3 #!/bin/sh set ‘who -m‘ echo Here are the positional variables that have been set: echo The first is: $1 echo The second is: $2 echo The third is: $3 echo The fourth is: $4 echo The fifth is: $5 echo The sixth is: $6 echo This script is: $0 $ ^d 使用chmod命令使脚本可以执行: $ chmod 755 script3 $ 执行新脚本: $ my.script3 Here are the positional variables that have been set: The first is: user1 The second is: pts/5 The third is: Mar The fourth is: 13 The fifth is: 11:43 The sixth is: (host1) This script is: my.script3 $ Bourne shell最多允许使用9个位置参数,$1到$9。脚本名称另外放在参数$0的引用中。 位置参数含义 $1到$9引用$1到$9位置参数 $0 引用当前shell脚本名称 另外两个有用的位置参数是$#和$@。 1、$#:返回存储在$1到$9位置参数的命令行参数总数; 2、$@:展开位置参数,显示每个存储的参数; 下面的示例说明脚本中位置参数的作用。 创建名为my.script4的脚本,更改属性为可执行。 $ vi my.script4 #!/bin/sh echo The script name is: $0 echo echo The first argument passed is: $1 echo The second argument passed is: $2 echo echo The highest numbered parameter is: $# echo The parameters passed to the script are: $@ ^d $ chmod 755 script4 $ 执行新脚本,带stop和start参数。 $ my.script4 start stop The script name is: my.script4 The first argument passed is: start The second argument passed is: stop The highest numbered parameter is: 2 The parameters passed to the script are: start stop $ 条件结构和流程控制 条件命令 条件命令允许你基于一个条件真假来执行相应的任务。最简单的条件命令是if命令。 If命令可以测试条件,根据条件测试的结果,来改变脚本执行的流程。 命令格式 if command then command command fi 退出状态 当程序完成执行后(命令行或者脚本),返回一个退出状态,然后回到shell,一个退出状态是一个0到255的整数。 根据上面给出的通用命令格式,if结构之后的命令被执行,并返回退出状态。如果退出状态为0在then和fi结构之间的命令被执行,fi终止if块。 但是,如何第一个命令执行后,退出状态非零,表示命令失败,then关键字以后的语句被忽略,流程之间跳到fi语句后面。 无效的参数传递、检测到错误条件都可以引起命令失败。 Shell变量$?由shell自动设置最后执行的命令的退出状态,echo命令可以显示参数值。 下面的示例描述了如何在命令行方式下查看一个成功和不成功的命令执行的退出状态。 $ mkdir newdir $ $ echo $? 0 $ $ mkdir mkdir: Failed to make directory "newdir"; File exists $ echo $? 127 $ test命令 内建的test命令通常紧跟if命令使用。 Test命令用来计算表达式的值,如果结果为真,返回零退出状态,如果结果为假,返回非零退出状态。 命令格式 if test expression then command fi 下面示例用于测试变量$name是否已经被预先设置为值user2? if test "$name" = "user2" then echo "matches" fi 等号操作符用于测试两个值是否一样?也就是说,test命令用来测试$name变量是否为字符串user2,如果是的话,返回零退出状态,否则返回非零退出状态。 test的另外一种格式 test命令通常用在shell脚本中,shell还可以识别test命令的另外一种格式,括号[]实际代表test命令。 前面的命令可以改写为如下形式: if [ “$name” = "user2" ] . . . shell还是执行了test命令,也只有用这种格式,test希望在表达式的结尾有一个]括号。在第一个括号[之后和最后一个括号]之前必须有空格。 命令格式 if [ expression ] then command command fi 下面的示例用于测试一个表达式的值,如果结果为真,返回零退出状态,结果为假,返回非零退出状态。 创建一个名为my.script5的脚本,使它可以执行,并执行该脚本。 $ vi >; my.script5 #!/bin/sh if name=user5 [ "$name" = "user5" ] echo $? then name=user7 [ "$name" = "user5" ] echo $? $ $ chmod 755 my.script5 $ my.script5 0 1 $ test命令操作符 几乎每个shell脚本都要处理一个或多个脚本,因此test命令有一系列用于分类的文件操作符,这些对文件操作符使得你可以在建立脚本时提供工具用于询问有关文件的问题。 下面列出了最常用的文件操作符: 操作符返回真(零退出状态)如果 -d file file为目录 -f file file为普通文件 -r file file可以被进程读取 -s file file长度非零 -w file file可以被进程写 -x file file可执行 下面的示例描述如何使用文件操作符来测试文件是否存在。 创建脚本,命名为my.script6,使它可执行,并运行该脚本,在最后一步,检查退出状态的结果。 $ vi my.script6 #!/bin/sh if [ -f $HOME ] then echo "found it!" fi $ chmod 755 my.script6 $ my.script6 found it! $ echo $? 0 $ case命令 case命令用于有多个条件测试的情况。 命令格式 case value in value1 ) command command ;; value2 ) command command ;; value3 ) command command ;; * ) command ;; esac case的值 case变量的值分别匹配value1, value2,等等,直到发现了一个匹配。 如果case变量的值并没有匹配,程序执行值* )后的命令,直到双括号或者esac。 下面示例展示了如何使用case命令: $ vi my.script7 #!/bin/sh hour=‘date | cut -c12-13‘ echo $hour case "$hour" in 0? | 1[01]) echo "Good Morning." ;; 1[2-7]) echo "Good Afternoon." ;; *) echo "Good Evening." ;; esac $ chmod 755 my.script7 $ my.script7 16 Good Afternoon. $ case命令计算$hour的值,存储在case变量中的值为当前时间,date命令把它的输出通过管道送到cut命令中,cut命令剪切小时,通过从输出中选择字符12和13。 Case变量的值$hour匹配每一个值,直到发现了一个匹配,然后结果回显到屏幕上。 1、第一个测试值用于确定case变量的值是否匹配上午的小时数?(例如, 1:00 am 到 11:00 am): 0? | 1[01] ),0?为字符0和用于匹配单个字符的通配符?。因此可能的测试值为01, 02, 03, 04, 05, 06, 07, 08, 09。|是or语句。1[01]是数字1和用于单个字符的通配符[ ],这里的可能测试值为10和11。 2、第二个测试值用于确定case变量的值是否匹配下午的小时数?(例如, 12:00 pm 到 5:00 pm): 1[2-7] ),可能的测试值为12, 13, 14, 15, 16, 17。 3、第三个测试值用于确定case变量的值是否匹配晚上的小时数?(例如, 6:00 pm 到 12:00 am): *),可能的测试值为18, 19, 20, 21, 22, 23,24。 exit命令 内建的称为exit的shell命令使用户可以立即终止shell脚本的执行。Exit经常作为结束、跳出或者返回命令行的命令使用。 命令格式 exit n exit命令中的参数取值范围为0-255的整数。 可以在脚本中放置一个或者多个exit命令,用来告诉shell在特定条件满足时退出脚本,这优先于脚本正常结束。 在大的脚本文件中,使用不同的整数来作为不同exit命令的参数,当需要确定某一具体条件满足时是非常有用的。 如果脚本以0为参数退出,说明程序成功执行,正常结束。非零参数(1-255)s说明出现了某些类型的错误。 用户可以使用echo命令来快速识别exit结果: $ echo $? 阅读一个Solaris管理脚本示例 下面给出的Solaris管理脚本示例是一个在目录/etc/init.d中维护。 这些脚本可以在系统启动的时候使用,也可以在系统关闭的使用使用。 系统管理员可以手动启动或者停止系统守护进程和服务,通过执行一个带参数stop和start管理脚本。 例如,要手动停止或者启动audit程序,root用户可以调用以下命令: # /etc/init.d/audit stop # /etc/init.d/audit start 使用前面学到的shell脚本知识,逐行分析下面脚本,确定程序执行时会发生什么事情: /etc/init.d/audit脚本 1 #!/sbin/sh 2 # 3 # Copyright (c) 1997 by Sun Microsystems, Inc. 4 # All rights reserved. 5 # 6 #ident "@(#)audit 1.5 97/12/08 SMI" 7 8 case "$1" in 9 ’start’) 10 if [ -f /etc/security/audit_startup ]; then 11 echo ’starting audit daemon’ 12 /etc/security/audit_startup 13 /usr/sbin/auditd & 14 fi 15 ;; 16 17’stop’) 18 if [ -f /etc/security/audit_startup ]; then 19 /usr/sbin/audit -T 20 fi 21 ;; 22 23*) 24 echo "Usage: $0 { start | stop }" 25 exit 1 26 ;; 27esac 28exit 0 audit管理脚本的解释 下面逐行解释执行audit脚本发生的事情: 第1行: #!/sbin/sh,说明用于执行程序的shell,这里为Bourne shell; 第2-6行: 注释行,以#开头; 第7行: 空白行 第8行:case表达式,赋予case的变量是位置参数$1,变量传递第一个命令行参数给脚本。 第9行: 说明赋予case的变量的第1个匹配值,本例中为start;如果两个值匹配,结果为真,返回一个零退出状态(0),脚本跳到下一行,第10行。如果两个值不匹配,结果为假,返回一个非零退出状态,脚本直接跳到;;之后语句,这里为第16行; 第10行: if条件语句,测试一个表达式的值;如果文件/etc/security/audit_startup 存在,结果为真,跳到下一行,第11行。如果文件/etc/security/audit_startup不存在,脚本直接跳去执行fi语句,这里为第15行; 第11行:执行echo命令,来显示starting audit daemon到屏幕上; 第12行:执行audit_startup脚本初始化audit子系统的安全性高于实际启动的audit守护进程的安全性; 第13行: 启动audit守护进程,该程序控制audit跟踪文件的产生,以及audit跟踪文件的位置; 第14行: if块语句结束标志; 第15行: 发送流程控制指令,使得脚本直接跳到esac语句之后执行,第16到27行跳过,不被执行; 第16行: 空白行; 第17行: 说明case变量的第二个值,这里为stop;如果两个值匹配,结果为真,返回一个零退出状态(0),脚本跳到下一行执行,也就是第18行,如果两个值不匹配,结果为假,返回一个非零退出状态,脚本直接跳到;;后的语句,这里为第22行; 第18行: if条件语句,测试一个表达式的值;如果文件/etc/security/audit_startup存在,结果为真,脚本执行下一行,即第19行,如果文件/etc/security/audit_startup不存在,关键字之后的语句被忽略,脚本跳去执行;;后的语句,这里为第21行; 第19行: 执行/usr/sbin/audit –T函数,来给audit守护进程发信号,告诉audit守护进程关闭当前audit跟踪文件,使监听失效、死亡; 第20行: 终止if块语句; 第21行: 发送流程控制指令,使得脚本直接跳到esac语句之后执行,第22到27行跳过,不被执行; 第22行: 空白行; 第23行: 如果case变量不能匹配第9行和第17行的值,shell执行第24、25行的命令; 第24行: 执行echo命令,显示如下文本字符串到屏幕: string to the screen: Usage: /etc/init.d/audit { start | stop } 第25行: 执行exit命令立即终止执行脚本,并返回到命令行状态下;指示程序中出现某些类型的错误; 第26行: 发送流程控制指令,脚本直接跳到esac语句后的最后一行; 第27行: 终止case块语句; 第28行: 执行exit命令,终止执行脚本,返回到命令行状态下,只是程序成功退出。
...全文
39 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复

477

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧