接上shell强大功能实例珍藏:再次跟随我的脚步一起去感受和学习shell的强大功能;根据应用实例带动对shell的学习.
将脚本参数传入系统命令
可以向脚本传递位置参数,然后测试变量。这里,如果用户在脚本名字后键入目录名,
脚本将重设$ 1特殊变量为一更有意义的名字。即D I R E C TO RY。这里需测试目录是否为空,如
果目录为空,ls -A将返回空,然后对此返回一信息。
- # ifdirec.sh
- # assigning $1 to DIRECTORY variable
- DIRECTORY=$1
- if [ "`ls -A $DIRECTORY`" == "" ]; then
- # if it's an empty string, then it's empty
- echo "$DIRECTORY is indeed empty"
- else
- # otherwise it is not
- echo "$DIRECTORY is not empty"
- fi
也可以使用下面的脚本替代上面的例子并产生同样的结果。
- [root@localhost ~]# cat ifdirec2.sh
- #!/bin/sh
- # ifdirec2
- DIRECTORY=$1
- if [ -z "`ls -A $DIRECTORY`" ]
- then
- echo "$DIRECTORY is indeed empty"
- else
- echo "$DIRECTORY is not empty"
null:命令用法
到目前为止,条件测试已经讲完了t h e n和e l s e部分,有时也许使用者并不关心条件为真或
为假。
不幸的是i f语句各部分不能为空—一些语句已经可以这样做。为解决此问题, s h e l l提供
了:空命令。空命令永远为真(也正是预想的那样)。回到前面的例子,如果目录为空,可以
只在t h e n部分加入命令。
- [root@localhost ~]# cat ifdirectory.sh
- #!/bin/sh
- # ifdirectory.sh
- DIRECTORY=$1
- if [ "`ls -A $DIRECTORY`" == "" ]
- then
- echo "$DIRECTORY is indeed empty"
- else :
- # do nothing
- fi
- [root@localhost ~]# ./ifdirectory.sh testd
- testd is indeed empty
测试目录创建结果
现在继续讨论目录,下面的脚本接受一个参数,并用之创建目录,然后参数被传入命令
行,重设给变量D I R E C TO RY,最后测试变量是否为空。
if ["$DIRECTORY"=""]
也可以用
if[$# -lt 1]
来进行更普遍的参数测试。
如果字符串为空,返回一可用信息,脚本退出。如果目录已经存在,脚本从头至尾走一
遍,什么也没做。
创建前加入提示信息,如果键入Y或y,则创建目录,否则使用空命令表示不采取任何动作。
使用最后命令状态测试创建是否成功执行,如果失败,返回相应信息。
- [root@localhost ~]# cat ifmkdir.sh
- #!/bin/sh
- # ifmkdir.sh
- # parameter is passed as $1 but reassigned to DIRECTORY
- DIRECTORY=$1
- # is the string empty ??
- if [ "$DIRECTORY" == "" ]
- then
- echo "Usage :`basename $0` directory to create" >&2
- exit 1
- fi
- if [ -d $DIRECTORY ]
- then : # do nothing
- else
- echo "The directory does not exist"
- echo -n "Create it now? [y..n] :"
- read ANS
- if [ "$ANS" == "y" ] || [ "$ANS" == "Y" ]
- then
- echo "creating now"
- # create directory and send all output to /dev/null
- mkdir $DIRECTORY > /dev/null 2>&1
- if [ $? != 0 ]; then
- echo "Errors creating the directory $DIRECTORY" >&2
- exit 1
- fi
- else : # do nothing
- fi
- fi
- [root@localhost ~]# ./ifmkdir.sh dt
- The directory does not exist
- Create it now? [y..n] :y
- creating now
另一个拷贝实例
在另一个拷贝实例中,脚本传入两个参数(应该包含文件名),系统命令c p将$ 1拷入$ 2,
输出至/ d e v / n u l l。如果命令成功,则仍使用空命令并且不采取任何动作。
另一方面,如果失败,在脚本退出前要获知此信息。
- [root@localhost ~]# cat ifcp2.sh
- #!/bin/sh
- # ifcp2.sh
- if cp $1 $2 > /dev/null 2>&1
- # successful, great do nothing
- then :
- else
- # oh dear, show the user what files they were.
- echo "`basename $0`: ERROR failed to copy $1 to $2"
- exit 1
- fi
- [root@localhost ~]# ./ifcp2.sh myfile.lex myfile.lex.bak
- ifcp2.sh: ERROR failed to copy myfile.lex to myfile.lex.bak
- [root@localhost ~]# touch myfile.lex
- [root@localhost ~]# ./ifcp2.sh myfile.lex myfile.lex.bak
上面展现了脚本运行成功和脚本运行失败的情况。
下面的脚本用s o r t命令将文件a c c o u n t s . q t r分类,并输出至系统垃圾堆。没人愿意观察屏幕
上3 0 0行的分类页。成功之后不采取任何动作。如果失败,通知用户。
- [root@localhost ~]# cat ifsort.sh
- #!/bin/sh
- # ifsort
- if sort accounts.qtr > /dev/null
- # sorted. Great
- then :
- else
- # better let the user know
- echo "`basename $0`: Oops..errors could not sort accounts.qtr"
- fi
多个if语句
可能有时要嵌入i f语句。为此需注意i f和f i的相应匹配使用。
=====================================GNU/LinuxFreeBSD==================================
测试和设置环境变量
前面已经举例说明了如何测试环境变量E D I TO R是否被设置。现在如果未设置,则进一步
为其赋值,脚本如下:
- #!/bin/sh
- # ifseted.sh
- # is the EDITOR set?
- if [ -z $EDITOR ]; then
- echo "Your EDITOR environment is not set"
- echo "I will assum you want to use vi .. OK"
- echo -n "Do you wish to change it now? [y..n] :"
- read ANS
- # check for an upper or lower case 'y'
- if [ "$ANS" == "Y" ] || [ "$ANS" == "y" ]; then
- echo "enter you editor type :"
- read EIDTOR
- if [ -z $EDITOR ] || [ "$EDITOR" == "" ]; then
- # if EDITOR not set and no value in variable EDITOR,
- # then set it to vi
- echo "No, editor entered, using vi as default"
- EDITOR=vi
- export EDITOR
- fi
- # got a value use it for EDITOR
- EDITOR=$EDITOR
- export EDITOR
- echo "setting $EDITOR"
- fi
- else
- # user
- echo "Using vi as the default editor"
- EDITOR=vi
- export EDITOR
- fi
脚本工作方式如下:首先检查是否设置了该变量,如果已经赋值,输出信息提示使用v i作
为缺省编辑器。v i被设置为编辑器,然后脚本退出。
如果未赋值,则提示用户,询问其是否要设置该值。检验用户输入是否为大写或小写y,
输入为其他值时,脚本退出。
如果输入Y或y,再提示输入编辑类型。使用$ E D I TO R =“”测试用户是否未赋值和未点
击r e t u r n键。一种更有效的方法是使用-z $EDITO R方法,本文应用了这两种方法。如果测试
失败,返回信息到屏幕,即使用v i做缺省编辑器,因而E D I TO R赋值为v i。
如果用户输入了一个名字到变量E D I TO R,则使用它作为编辑器并马上让其起作用,即导
出变量E D I TO R。
检测最后命令状态
前面将目录名传入脚本创建了一个目录,脚本然后提示用户是否应创建目录。下面的例
子创建一个目录,并从当前目录将所有* . t x t文件拷入新目录。但是这段脚本中用最后状态命
令检测了每一个脚本是否成功执行。如果命令失败则通知用户。
- #!/bin/sh
- # ifmkdir2.sh
- DIR_NAME=testdirec
- # where are we?
- THRER=`pwd`
- # send all output to the system dustbin
- mkdir $DIR_NAME > /dev/null 2>&1
- # is it a directory ?
- if [ -d $DIR_NAME ]; then
- # can we cd to the directory
- cd $DIR_NAME
- if [ $? == 0 ]; then
- # yes we can
- HERE=`pwd`
- cp $THERE/*.txt $HERE
- else
- echo "Cannot cd to $DIR_NAME" >&2
- exit 1
- fi
- else
- echo "Cannnot create directory $DIR_NAME" >&2
- exit 1
- fi
增加和检测整数值
下面的例子进行数值测试。脚本包含了一个计数集,用户将其赋予一个新值就可改变它。
脚本然后将当前值1 0 0加入一个新值。工作流程如下:
用户输入一个新值改变其值,如果键入回车键,则不改变它,打印当前值,脚本退出。
如果用户用y或Y响应新值,将提示用户输入增量。如果键入回车键,原值仍未变。键入
一个增量,首先测试是否为数字,如果是,加入计数C O U N TO R中,最后显示新值。
- #!/bin/sh
- # ifcounter.sh
- COUNTER=100
- echo "Do you wish to change the counter value currently set at $COUNTER
- [y..n] :"
- read ANS
- if [ "$ANS" == "y" ] || [ "$ANS" == "Y" ]; then
- # yes user wants to change the value
- echo "Enter a sensible value "
- read VALUE
- # simple test to see if it's numeric, add any number to VALUE,
- # then check out return
- # code
- expr $VALUE + 10 > /dev/null 2>&1
- STATUS=$?
- # check return code of expr
- if [ "$VALUE" == "" ] || [ "$STATUS" != "0" ]; then
- # send errors to standard error
- echo " You either entered nothing or a non-numeric " >&2
- echo " Sorry now exiting...counter stays at $COUNTER" >&2
- exit 1
- fi
- # if we are here, then it's a number, so add it to COUNTER
- COUNTER=`expr $COUNTER + $VALUE`
- echo " Counter now set to $COUNTER"
- else
- # if we are here user just hit return instead of entering a number
- # or anssered n to the change a value prompt
- echo " Counter stays at $COUNTER"
- fi
下面是程序的运行结果:
- [root@localhost ~]# ./ifcounter.sh
- Do you wish to change the counter value currently set at 100
- [y..n] :
- n
- Counter stays at 100
- [root@localhost ~]# ./ifcounter.sh
- Do you wish to change the counter value currently set at 100
- [y..n] :
- y
- Enter a sensible value
- fdg
- You either entered nothing or a non-numeric
- Sorry now exiting...counter stays at 100
- [root@localhost ~]# ./ifcounter.sh
- Do you wish to change the counter value currently set at 100
- [y..n] :
- y
- Enter a sensible value
- 250
- Counter now set to 350
=====================================GNU/LinuxFreeBSD==================================
以下是用户登录时启动应用前加入相应安全限制功能的基本框架。首先提示输入用户名
和密码,如果用户名和密码均匹配脚本中相应字符串,用户登录成功,否则用户退出。
脚本首先设置变量为假—总是假定用户输入错误, s t t y当前设置被保存,以便隐藏
p a s s w d域中字符,然后重新保存s t t y设置。
如果用户I D和密码正确(密码是easypasswd),明亮I N VA L I D U S E R和I N VA L I D PA S S W D设
置为n o表示有效用户或密码,然后执行测试,如果两个变量其中之一为y e s,缺省情况下,脚
本退出用户。
键入有效的I D和密码,用户将允许进入。这是一种登录脚本的基本框架。下面的例子中
有效用户I D为root。
提示:在实际中千万不要这么做,任何人都知道用root身份进行测试是很危险的。
- #!/bin/sh
- # ifpass.sh
- # set the variables to false
- INVALID_USER=yes
- INVALID_PASSWD=yes
- # save the current stty settings
- SAVEDSTTY=`stty -g`
- echo "You are logging into a sensitive area"
- echo -n "Enter your ID name :"
- read NAME
- # hide the characters typed in
- stty -echo
- echo "Enter your password :"
- read PASSWORD
- # back on again
- stty $SAVEDSTTY
- if [ "$NAME" == "root" ]; then
- # if a valid then set variable
- INVALID_USER=no
- fi
- if [ "$PASSWORD" == "easypasswd" ]; then
- # if valid password then set variable
- INVALID_PASSWD=no
- fi
- if [ "$INVALID_USER" == "yes" -o "$INVALID_PASSWD" == "yes" ]; then
- echo "`basename $0 :` Sorry wrong password or userid"
- exit 1
- fi
- # if we get here then their ID and password are OK.
- echo "correct user id an password given"
下面是对应两种不同情况的输出结果。
- [root@localhost ~]# ./ifpass.sh
- You are logging into a sensitive area
- Enter your ID name :root
- Enter your password :
- correct user id an password given
- [root@localhost ~]# ./ifpass.sh
- You are logging into a sensitive area
- Enter your ID name :root
- Enter your password :
- ifpass.sh Sorry wrong password or userid
elif用法
if then else语句的e l i f部分用于测试两个以上的条件。
使用elif进行多条件检测
使用一个简单的例子,测试输入脚本的用户名。脚本首先测试是否输入一个名字,如果
没有,则什么也不做。如果输入了,则用e l i f测试是否匹配r o o t、l o u i s e或d a v e,如果不匹配其
中任何一个,则打印该名字,通知用户不是r o o t、l o u i s e或d a v e。
- #!/bin/sh
- # ifelif.sh
- echo -n "enter your login name :"
- read NAME
- # no name entered do not carry on
- if [ -z $NAME ] || [ "$NAME" == "" ]; then
- echo "You did not enter a name"
- elif
- # is the name root
- [ "$NAME" == "root" ]; then
- echo "Hello root"
- elif
- # or is it louise
- [ $NAME == "louise" ]; then
- echo "Hello louise"
- elif
- # or is it dave
- [ "$NAME" == "dave" ]; then
- echo "Hello dave"
- else
- # no it's somebody else
- echo "You are not root or louise or dave but hi $NAME"
- fi
- 运行上述脚本,给出不同信息,得结果如下:
- [root@localhost ~]# chmod +x ifelif.sh
- [root@localhost ~]# ./ifelif.sh
- enter your login name :dave
- Hello dave
- [root@localhost ~]# ./ifelif.sh
- enter your login name :
- You did not enter a name
- [root@localhost ~]# ./ifelif.sh
- enter your login name :Peter
- You are not root or louise or dave but hi Peter
多文件位置检测
假定要定位一个用户登录文件,已知此文件在/ u s r / o p t s / a u d i t / l o g s或/ u s r / l o c a l / a u d i t / l o g s中,
具体由其安装人决定。在定位此文件前,首先确保文件可读,此即脚本测试部分。如果未找
到文件或文件不可读,则返回错误信息。脚本如下:
- #!/bin/sh
- # ifcataudit.sh
- # locations of the log file
- LOCAT_1=/usr/opts/audit/logs/audit.log
- LOCAT_2=/usr/local/audit/audit.logs
- if [ -r $LOCAT_1 ]; then
- # if it is in this directory and is readable then cat is
- echo "Using LOCAT_1"
- cat $LOCAT_1
- elif
- # else it then must be in this direcotory, and is it readable
- [ -r $LOCAT_2 ]
- then
- echo "Using LOCAT_2"
- cat $LOCAT_2
- else
- # not in any of the directories...
- echo "`basename $0`: Sorry the audit file is not readable or cannot be
- localted." >&2
- exit 1
- fi
运行上面脚本,如果文件在上述两个目录之一中并且可读,将可以找到它。如果不是,
返回错误并退出,下面结果失败,因为假想的文件并不存在
- [root@localhost ~]# ./ifcataudit.sh
- ifcataudit.sh: Sorry the audit file is not readable or cannot be
- localted.
到了此处又得告一段落了,精彩过后就是回味无穷;这些只得深思和深入的研究慢慢学知识的海洋中要学的东西很多但不可能短时间内学完;人生就是在一天天的学习一天天的成长,该上班了就先写这么多吧。