实验9Shell Script2.docx
《实验9Shell Script2.docx》由会员分享,可在线阅读,更多相关《实验9Shell Script2.docx(23页珍藏版)》请在冰点文库上搜索。
实验9ShellScript2
实验九:
ShellScript
1实验目的
通过实验掌握Linuxbash
2实验设备
硬件:
PC机一台
软件:
Windows98/XP/2000系统,VMwareWorkstation6.0,RedHatLinux
3实验内容
(1)Shell中的变量:
用户自定义变量与环境变量
(2)命令别名
(3)Bashshell的操作环境
(4)数据流重定向
(5)管道命令
4实验预习要求
仔细阅读参考书:
【1】鸟哥的Linux私房菜基础学习篇第三版,人民邮电出版社,鸟哥
【2】嵌入式Linux系统开发标准教程,人民邮电出版社,华清远见嵌入式培训中心
【3】嵌入式Linux应用程序开发标准教程,人民邮电出版社,华清远见嵌入式培训中心
5实验步骤
略
6实验重点:
(1)命令执行的判断依据:
;&&||
(2)善用判断式
利用test命令的测试功能
当要检测系统上面某些文件或者是相关的属性时,利用test这个命令来工作。
如要检查/panyin是否存在时,使用:
[root@localhost~]#test-e/panyin
运行结果并不会显示任何信息,但可以通过$?
或&&及||来展现整个结果!
例如在将上面的例子改写成这样:
[root@localhost~]#test-e/panyin&&echo"exist"||echo"Notexist"
Notexist<==结果显示不存在!
最终的结果可以告知我们是exist还是Notexist!
这里-e是测试一个东西存在不存在,相关的参数如下:
测试的标志代表意义
1.关于某个文件名的文件类型判断,如test-efilename表示存在否
-e该文件名是否存在?
(常用)
-f该文件名是否存在且为文件(file)?
(常用)
-d该文件名是否存在且为目录(directory)?
(常用)
-b该文件名是否存在且为一个blockdevice装置?
-c该文件名是否存在且为一个characterdevice装置?
-S该文件名是否存在且为一个Socket文件?
-p该文件名是否存在且为一个FIFO(pipe)文件?
-L该文件名是否存在且为一个连结文件?
2.关于文件的权限检测,如test-rfilename表示可读否(但root权限常有例外)
-r检测该文件名是否存在且具有可读的权限?
-w检测该文件名是否存在且具有可写的权限?
-x检测该文件名是否存在且具有可运行的权限?
-u检测该文件名是否存在且具有SUID的属性?
-g检测该文件名是否存在且具有SGID的属性?
-k检测该文件名是否存在且具有Stickybit的属性?
-s检测该文件名是否存在且为非空白文件?
3.两个文件之间的比较,如:
testfile1-ntfile2
-nt(newerthan)判断file1是否比file2新
-ot(olderthan)判断file1是否比file2旧
-ef判断file1与file2是否为同一文件,可用在判断hardlink的判定上。
主要意义在判定两个文件是否均指向同一个inode!
4.关于两个整数之间的判定,例如testn1-eqn2
-eq两数值相等(equal)
-ne两数值不等(notequal)
-gtn1大于n2(greaterthan)
-ltn1小于n2(lessthan)
-gen1大于等于n2(greaterthanorequal)
-len1小于等于n2(lessthanorequal)
5.判定字串的数据
test-zstring判定字串是否为0?
若string为空字串,则为true
test-nstring判定字串是否非为0?
若string为空字串,则为false。
注:
-n亦可省略
teststr1=str2判定str1是否等于str2,若相等,则回传true
teststr1!
=str2判定str1是否不等于str2,若相等,则回传false
6.多重条件判定,例如:
test-rfilename-a-xfilename
-a(and)两条件同时成立!
例如test-rfile-a-xfile,则file同时具有r与x权限时,才回传true。
-o(or)任何一个成立!
例如test-rfile-o-xfile,则file具有r或x权限时,就可回传true。
!
反相状态,如test!
-xfile,当file不具有x时,回传true
示例:
程序实现如下功能:
1判断文件是否存在,若不存在则给予一个Filenamedoesnotexist的信息,并中断程序;
2若这个文件存在,则判断他是个文件或目录,结果输出Filenameisregularfile或Filenameisdirectory
3判断执行者的身份对这个文件或目录所拥有的权限,并输出权限数据!
注意利用test与&&还有||等标志!
[root@localhostscripts]#vish05.sh
#!
/bin/bash
#Program:
#Userinputafilename,programwillchecktheflowing:
#1.)exist?
2.)file/directory?
3.)filepermissions
#History:
#2012-03-20HBUEFirstrelease
#1.让使用者输入文件名,并且判断使用者是否真的有输入字串?
echo-e"Pleaseinputafilename\n"
read-p"Inputafilename:
"filename
test-z$filename&&echo"YouMUSTinputafilename."&&exit0
#2.判断文件是否存在?
若不存在则显示信息并结束脚本
test!
-e$filename&&echo"Thefilename'$filename'DONOTexist"&&exit0
#3.开始判断文件类型与属性
test-f$filename&&filetype="regularefile"
test-d$filename&&filetype="directory"
test-r$filename&&perm="readable"
test-w$filename&&perm="$permwritable"
test-x$filename&&perm="$permexecutable"
#4.开始输出信息!
echo"Thefilename:
$filenameisa$filetype"
echo"Andthepermissionsare:
$perm"
运行这个脚本后,会依据输入的文件名来进行检查!
但必须要注意的是,由于root在很多权限的限制上面都是无效的,所以使用root运行这个脚本时,常常会发现与ls-l观察到的结果并不相同!
所以,建议使用一般使用者来运行这个脚本。
不过必须要使用root的身份先将这个脚本转移给使用者,不然一般使用者无法进入/root目录的。
(3)判断符号[]
除了使用的test之外,还可以利用判断符号[]来进行数据的判断!
举例如如果想要知道$HOME这个变量是否为空的,可以这样做:
[root@localhost~]#[-z"$HOME"];echo$?
使用中括号必须要特别注意,因为中括号用在很多地方,包括通配符与正则表达式等等,所以如果要在bash的语法当中使用中括号作为shell的判断式时,必须要注意中括号的两端需要有空格符来分隔!
假设空格键使用□符号来表示,那么,在这些地方你都需要有空格键:
["$HOME"=="$MAIL"]
[□"$HOME"□==□"$MAIL"□]
↑↑↑↑
在上面的判断式当中使用了两个等号==。
其实在bash当中使用一个等号与两个等号的结果是一样的!
不过在一般惯用程序的写法中,一个等号代表变量的设置,两个等号则是代表逻辑判断。
由于在中括号内重点在于判断而非设置变量,因此建议还是使用两个等号较佳!
上面的例子在说明,两个字串$HOME与$MAIL是否相同的意思,相当于test$HOME=$MAIL的意思!
而如果没有空白分隔,例如[$HOME==$MAIL]时,bash就会显示错误信息了!
在中括号[]内的每个组件都需要有空格键来分隔;
在中括号内的变量,最好都以双引号括号起来;
在中括号内的常数,最好都以单或双引号括号起来。
为什么要这么麻烦?
直接举例来说,假如设置了name="HBUEEE",然后这样判定:
[root@localhost~]#name="HBUEEE"
[root@localhost~]#[$name=="HBUE"]
bash:
[:
toomanyarguments
怎么会发生错误?
bash的错误是由于太多参数(arguments)所致!
为什么呢?
因为$name如果没有使用双引号刮起来,那么上面的判定式会变成:
[HBUEEE=="HBUE"]
上面肯定不对!
因为一个判断式仅能有两个数据的比对,上面HBUE与EE还有"HBUE"就有三个数据!
这不是我们要的!
应该是下面这个样子:
["HBUEEE"=="HBUE"]
另外,中括号的使用方法与test几乎一模一样。
只是中括号比较常用在条件判断式if.....then.....fi的情况中。
示例如下:
1当运行一个程序的时候,这个程序会让使用者选择Y或N,
2如果使用者输入Y或y时,就显示OK,continue
3如果使用者输入n或N时,就显示Oh,interrupt!
4如果不是Y/y/N/n之内的其他字节,就显示Idon'tknowwhatyourchoiceis
利用中括号、&&与||来实现上述功能!
[root@localhostscripts]#vish06.sh
#!
/bin/bash
#Program:
#Thisprogramshowstheuser'schoice
#History:
#2012-03-20HBUEFirstrelease
read-p"Pleaseinput(Y/N):
"yn
["$yn"=="Y"-o"$yn"=="y"]&&echo"OK,continue"&&exit0
["$yn"=="N"-o"$yn"=="n"]&&echo"Oh,interrupt!
"&&exit0
echo"Idon'tknowwhatyourchoiceis"&&exit0
由于输入正确(Yes)的方法有大小写之分,不论输入大写Y或小写y都是可以的,此时判断式内就得要有两个判断才行!
由于是任何一个成立即可(大小或小写的y),所以这里使用-o(或)!
(4)Shellscript的默认变量($0,$1...)
我们知道命令可以带有选项与参数,例如ls-la可以察看包含隐藏文件的所有属性与权限。
那么shellscript能不能在脚本文件名后面带有参数呢?
script针对参数已经有设置好一些变量名称!
对应如下:
/path/to/scriptnameopt1opt2opt3opt4
$0$1$2$3$4
如上:
运行的脚本文件名为$0这个变量,第一个接的参数就是$1。
还有一些较为特殊的变量可以在script内使用来呼叫这些参数喔!
$#:
代表后接的参数个数,以上表为例这里显示为4;
$@:
代表"$1""$2""$3""$4"之意,每个变量是独立的(用双引号括起来);
$*:
代表"$1c$2c$3c$4",其中c为分隔字节,默认为空格键,所以本例中代表"$1$2$3$4"之意。
那个$@与$*基本上还是有所不同!
不过,一般使用情况下可以直接记忆$@即可!
好了,来做个例子吧~假设我要运行一个可以携带参数的script,运行该脚本后屏幕会显示如下的数据:
程序的文件名为何?
共有几个参数?
若参数的个数小于2则告知使用者参数数量太少
全部的参数内容为何?
第一个参数为何?
第二个参数为何
[root@localhostscripts]#vish07.sh
#!
/bin/bash
#Program:
#Programshowsthescriptname,parameters...
#History:
#2009/02/17HBUEFirstrelease
PATH=/bin:
/sbin:
/usr/bin:
/usr/sbin:
/usr/local/bin:
/usr/local/sbin:
~/bin
exportPATH
echo"Thescriptnameis==>$0"
echo"Totalparameternumberis==>$#"
["$#"-lt2]&&echo"Thenumberofparameterislessthan2.Stophere."\
&&exit0
echo"Yourwholeparameteris==>'$@'"
echo"The1stparameter==>$1"
echo"The2ndparameter==>$2"
运行结果如下:
[root@localhostscripts]#shsh07.shtheonehahaquot
Thescriptnameis==>sh07.sh<==文件名
Totalparameternumberis==>3<==果然有三个参数
Yourwholeparameteris==>'theonehahaquot'<==参数的内容全部
The1stparameter==>theone<==第一个参数
The2ndparameter==>haha<==第二个参数
(4)条件判断式
●利用if....then
if....then是最常见的条件判断式
单层、简单条件判断式:
如果只有一个判断式要进行,那么可以简单的这样看:
if[条件判断式];then
当条件判断式成立时,可以进行的命令工作内容;
fi<==将if反过来写,就成为fi!
结束if之意!
条件判断式的判断方法,与前一小节的介绍相同!
较特别的是,如果有多个条件要判别时,除了将多个条件写入一个中括号内的情况之外,还可以有多个中括号来隔开!
而括号与括号之间,则以&&或||来隔开,他们的意义是:
&&代表AND;
||代表or;
例如,sh06.sh里面的判断式可以这样修改:
["$yn"=="Y"-o"$yn"=="y"]
上式可替换为
["$yn"=="Y"]||["$yn"=="y"]
将sh06.sh这个脚本修改成为if...then的样式:
[root@localhostscripts]#cpsh06.shsh06-2.sh<==用改的比较快!
[root@localhostscripts]#vish06-2.sh
#!
/bin/bash
#Program:
#Thisprogramshowstheuser'schoice
#History:
#2012-03-20HBUEFirstrelease
read-p"Pleaseinput(Y/N):
"yn
if["$yn"=="Y"]||["$yn"=="y"];then
echo"OK,continue"
exit0
fi
if["$yn"=="N"]||["$yn"=="n"];then
echo"Oh,interrupt!
"
exit0
fi
echo"Idon'tknowwhatyourchoiceis"&&exit0
●多重、复杂条件判断式
语法:
if[条件判断式];then
当条件判断式成立时,可以进行的命令工作内容;
else
当条件判断式不成立时,可以进行的命令工作内容;
fi
如果考虑更复杂的情况,则可以使用这个语法:
#多个条件判断(if...elif...elif...else)分多种不同情况运行
if[条件判断式一];then
当条件判断式一成立时,可以进行的命令工作内容;
elif[条件判断式二];then
当条件判断式二成立时,可以进行的命令工作内容;
else
当条件判断式一与二均不成立时,可以进行的命令工作内容;
fi
注意,elif也是个判断式,因此出现elif后面都要接then来处理!
但是else后面并没有then!
将sh06-2.sh改写成这样:
[root@localhostscripts]#cpsh06-2.shsh06-3.sh
[root@localhostscripts]#vish06-3.sh
#!
/bin/bash
#Program:
#Thisprogramshowstheuser'schoice
#History:
#2012-03-20HBUEFirstrelease
read-p"Pleaseinput(Y/N):
"yn
if["$yn"=="Y"]||["$yn"=="y"];then
echo"OK,continue"
elif["$yn"=="N"]||["$yn"=="n"];then
echo"Oh,interrupt!
"
else
echo"Idon'tknowwhatyourchoiceis"
fi
程序变得很简单。
一般来说,如果不希望使用者由键盘输入额外的数据时,可以使用上一节提到的参数功能($1)!
让使用者在执行命令时就将参数带进去!
如果想让使用者输入hello这个关键字时,利用参数的方法可以这样依序设计:
1判断$1是否为hello,如果是的话,就显示"Hello,howareyou?
";
2如果没有加任何参数,就提示使用者必须要使用的参数;
3而如果加入的参数不是hello,就提醒使用者仅能使用hello为参数。
程序如下:
[root@localhostscripts]#vish09.sh
#!
/bin/bash
#Program:
#Check$1isequalto"hello"
#History:
#2012-03-22HBUEFirstrelease
if["$1"=="hello"];then
echo"Hello,howareyou?
"
elif["$1"==""];then
echo"YouMUSTinputparameters,ex>{$0someword}"
else
echo"Theonlyparameteris'hello',ex>{$0hello}"
fi
●利用case.....esac判断
语法如下:
case$变量名称in<==关键字为case,还有变量前有钱字号
"第一个变量内容")<==每个变量内容建议用双引号括起来,关键字则为小括号)
程序段
;;<==每个类别结尾使用两个连续的分号来处理!
"第二个变量内容")
程序段
;;
*)<==最后一个变量内容都会用*来代表所有其他值
不包含第一个变量内容与第二个变量内容的其他程序运行段
exit1
;;
esac<==最终的case结尾!
反过来写!
要注意的是,每一个变量内容的程序段最后都需要两个分号(;;)来代表该程序段落的结束!
sh09.sh修改一下:
[root@localhostscripts]#vish09-2.sh
#!
/bin/bash
#Program:
#Show"Hello"from$1....byusingcase....esac
#History:
#2012-03-22HBUEFirstrelease
case$1in
"hello")
echo"Hello,howareyou?
"
;;
"")
echo"YouMUSTinputparameters,ex>{$0someword}"
;;
*)#其实就相当于通配符,0~无穷多个任意字节之意!
echo"Usage$0{hello}"
;;
esac
在上面这个sh09-2.sh的示例当中,如果你输入shsh09-2.shtest来运行,那么屏幕上就会出现Usagesh09-2.sh{hello}的字样,告知运行者仅能够使用hello这样的方式对于需要某些固定字串来运行的变量内容就显的更加的方便!
这种方式系统的很多服务的启动scripts都是使用这种写法的,如Linux的服务启动放置目录是在/etc/init.d/当中,我已经知道里头有个syslog的服务,我想要重新启动这个服务,可以这样做:
/etc/init.d/syslogrestart
重点是哪个restart!
如果你使用less/etc/init.d/syslog去查阅一下,就会看到他使用的是case语法,并且会规定某些既定的变量内容,可以直接执行/etc/init.d/syslog,