shell脚本.docx
- 文档编号:6658460
- 上传时间:2023-01-08
- 格式:DOCX
- 页数:23
- 大小:25.44KB
shell脚本.docx
《shell脚本.docx》由会员分享,可在线阅读,更多相关《shell脚本.docx(23页珍藏版)》请在冰豆网上搜索。
shell脚本
目录
9.5.1变量2
9.5.2条件测试5
9.5.3流程控制8
9.5.4函数14
9.5.5脚本实例16
脚本是为了缩短传统的“编写→编译→链接→运行”过程而创建的计算机编程语言。
此命名起源于一个脚本“screenplay”,每次运行都会使对话框逐字重复。
早期的脚本语言经常被称为批次处理语言或工作控制语言。
一个脚本通常是解释运行而非编译。
脚本语言通常都有简单、易学、易用的特性,目的就是希望能让程序设计师快速完成程序的编写工作。
虽然许多脚本语言都超越了计算机简单任务自动化的领域,成熟到可以编写精巧的程序,但仍然还是被称为脚本。
几乎所有计算机系统的各个层次都有一种脚本语言。
目前在许多方面,高级编程语言和脚本语言之间互相交叉,二者之间没有明确的界限。
bashShell提供了很强大的脚本功能,在脚本中可以执行命令或通过特定的语法完成指定的工作。
在开始学习Shell脚本前首先要了解以下内容。
(1)Shell脚本并不是一个复杂的程序语言,其是按行解释的。
每个Shell脚本对于文件系统来说就是一个文本文件,在有相应权限的情况下可以使用文本编辑器建立修改Shell脚本文件;使用文本查看命令显示Shell脚本的内容。
(2)虽然在Linux中扩展名并没有实际的作用但一般为了方便阅读,bashShell的脚本文件一般使用“sh”作为扩展名。
(3)一行中“#”之后的内容表示是注释,注释在执行过程中将被忽略。
(4)在Shell脚本文件的第一行应该指定向哪个解释器发送指令,目前在RHEL5.x中默认使用bashShell,所以第一行应该是“#!
/bin/sh”。
(5)在执行已编写好的脚本时可以使用两种方式:
对于有执行权限的脚本文件可以使用“./<文件名>”的方式执行;对于没有执行权限的脚本文件可以使用“sh<文件名>”的方式执行。
(6)Linux系统中每个进程都是有寿命的。
所有进程应另一个进程的请求而启动,发出请求的进程被称为父进程,新启动的进程被称为子进程。
在子进程完成自身的任务后退出。
子进程退出后会返回一个信息给父进程,叫做返回值或退出状态。
返回值是一个0~244之间的整数,进程返回0表示其执行成功,如果返回任何非0的值表示有某种形式的失败。
在bashshell中把上一个命令的返回值保存在一个名为“$?
”的特殊变量中,可以使用“echo$?
”显示上一个命令是否执行成功。
[root@srv~]#touchctu.txt
●返回值为0表示上一个命令“touchctu.txt”执行成功。
[root@srv~]#echo$?
0
[root@srv~]#ll/dod
ls:
/dod:
Nosuchfileordirectory
●返回值非0表示上一个命令“ll/dod”执行失败。
[root@srv~]#echo$?
2
●为什么再次使用“echo$?
”时又显示执行成功呢?
这是因为$?
只保存了上一个命令的返回值,对于$?
目前的值是上一个“echo$?
”的返回值,所以显示执行成功。
[root@srv~]#echo$?
0
9.5.1变量
变量简单地说就是会变化的量。
变量根据脚本确定自己的值。
变量可以理解为一个盒子,其根本特点就是“装载”特定的数值或字符。
bashShell允许用户设置和引用Shell变量。
Shell变量可以用在命令、脚本中,也可以被其他程序作为配置选项而引用。
Shell变量有两种类型:
环境变量和局部变量。
其中环境变量由子Shell继承,局部变量只存在于创建的Shell中。
每个变量都是一个名称,Shell变量的名称可以字母字符及下画线组成(变量名不能用数字开头)。
和大多数脚本语言一样,bashShell在使用变量前并不需专门的语句进行定义也不对变量区分数据类型。
本质上bashShell所有变量都是字符串。
当然在bashShell也允许比较操作和算术操作,这取决于变量中的值是否只有数字。
1.局部变量
Shell的局部变量建立和赋值直接使用“变量名=变量值”的方式,如下面的例子中定义了一个局部变量名称为strA,其值为ctu。
●定义一个名为strA的变量,并为其赋值“ctu”。
[root@srv~]#strA=ctu
●定义一个名为strB的变量,并为其赋值“dod”。
在为变量赋值时可以使用双引号,但不是必需的。
[root@srv~]#strB=“dod”
●在变量定义后,当前用户在不注销的情况下任何时间都可以使用已定义的变量。
在使用时必须在变量名前加一个$。
显示局部变量strA的值。
[root@srv~]#echo$strA
ctu
●已定义的变量可以在命令行或Shell脚本中使用,下面的命令将“CounterTerroristUnit”输入到一个名为ctu.txt的文件中。
[root@srv~]#echo“CounterTerroristUnit”>$strA.txt
[root@srv~]#catctu.txt
CounterTerroristUnit
在下面的例子中用户的本意是将“CounterTerroristUnit_1”输入到一个名为ctu.txt的文件中,但执行命令是bashShell会认为用户是要输入一个文件名为变量strA_1,扩展名为.txt的文件,所以在执行后输入的文件成了“.txt”(因为变量strA_1并没有被赋值)。
为了解决这个问题可以使用大括号{}标出变量名。
[root@srv~]#echo“CounterTerroristUnit_l”>$strA_1.txt
[root@srv~]#ll*.txt
-rw-r--r--lrootroot23Mar1100:
45ctu.txt
[root@srv~]#cat.txt
CounterTerroristUnit_1
[root@srv~]#echo“CounterTerroristUnit_1”>${strA}_1.txt
[root@srv~]#ll*.txt
-rw-r--r--lrootroot25Mar1100:
46ctu_1.txt
-rw-r--r--lrootroot23Mar1100:
45ctu.txt
在bashShell中会自动设置一些变量为用户提供信息,这些变量是只读的,用户可以读取但不能修改。
这样由bashShell自动设置的变量主要包括以下几个。
(1)?
:
最后一个命令的返回值。
$?
(2)$:
当前的Shell的进程id。
$$
(3)!
:
最新后台命令的进程id。
(4)_:
前一个命令最后的标记。
(5)PPID:
Shell父进程的进程id。
(6)UID:
当前用户的用户id。
(7)BASH_VERSION:
当前bash的版本。
(8)HOSTNAME:
当前计算机制主机名。
(9)OLDPWD:
上一次的工作目录。
(10)PWD:
当前工作目录。
(11)RANDOM:
在0~32767之间随机整数。
(12)SECONDS:
Shell启动以来的秒数。
●执行“ls-a”命令。
[root@srv~]#ls-a
~anaconda-ks.cfg.bashrc.gnome2install.log.redhatDesktop
install.log.syslogreports..bash_history
●显示最后一个命令最后的标记。
[root@srv~]#echo$_
-a
●显示当前工作目录。
[root@srv~]#echo$PWD
/root
●显示当前bash的版本。
[root@srv~]#echo$BASH_VERSION
3.2.25
(1)-release
2.环境变量
在bashShell中允许用户使用“变量名=变量值”的方式定义局部变量,而在Linux的内核中也允许全体进程使用“变量名=变量值”的方式定义被称作环境变量的变量。
环境变量是保存在内核进程中的一部分,无论何时一个进程启动另一个进程时,子进程都会继承环境变量。
用户也可以创建环境变量,然后所有被Shell启动的命令将会沿用这个变量。
环境变量创建分为两步:
定义一个局部变量;使用“export”命令将局部变量提升为环境变量。
●脚本sh1.sh的功能就是将“variablestrA=”和变量strA合并后显示。
[root@srv~]#catsh1.sh
#!
/bin/sh
echo“variablestrA=”$strA
●定义变量strA的值。
[root@srv~]#strA=“ctu”
[root@srv~]#echo$strA
ctu
●运行脚本sh1.sh。
[root@srv~]#./sh1.sh
●这时变量strA的值并没有被显示,这是因为变量strA目前是一个局部变量。
variablestrA=
●将变量strA提升为环境变量。
[root@srv~]#exportstrA
●再次运行脚本sh1.sh时,变量strA的值就可以被显示。
[root@srv~]#./sh1.sh
variablestrA=ctu
3.显示已定义的变量
在bashShell中可以通过set命令显示已定义的变量,env命令用于显示已定义的环境变量。
4.清除变量
对于已经定义的变量可以使用“unset<变量名>”的方式清除。
●定义变量strB。
[root@srv~]#strB=“dod”
●显示变量strB的内容。
[root@srv~]#echo$strB
dod
●清除变量strB。
[root@srv~]#unsetstrB
●再次显示时,变量strB已经没有内容。
[root@srv~]#echo$strB
5.向脚本传递参数
就像在执行Shell命令时经常会使用参数一样,很多时候编写的脚本需要接受传递给脚本的参数。
在脚本中可以使用“$1”接受传递给脚本的第一个参数、使用“$2”接受传递给脚本的第二个参数,除了可以获得每个参数值以外,还可以使用“$*”接受所有的参数、使用“$0”获取当前脚本的名称、使用“$#”获取传递给脚本的参数个数、使用“$$”获取当前脚本运行的PID。
●显示脚本sh2.sh的内容。
[root@srv~]#catsh2.sh
#!
/bin/sh
echo“ScriptNameIs:
”$0
echo“Firstvariable:
”$1
echo“SecondVariable:
”$2
echo“Tertiarynariable:
”$3
echo“AllVariable:
”$*
●执行脚本并传递三个参数。
[root@srv~]#./sh2.shctudodcia
ScriptNameIs:
./sh2.sh
FirstVariable:
ctu
SecondVariable:
dod
TertiaryVariable:
cia
AllVariable:
ctudodcia
9.5.2条件测试
在用户将参数传递给脚本或因为一些原因需要对一个对象进行测试,看是否满足某种条件。
在bashShell中提供了一些条件测试的语句,这些语句既可以在命令行中使用,也可能在脚本中使用。
提示
在下面的使用都是在交互模式中使用这些测试命令,在后面的章节中再讲述在Shell脚本中通过流程控制语句使用条件测试。
1.字符串测试
字符串测试经常用于检查用户输入的参数是否正确,字符串测试的方法如下。
test“字符串”
test<条件>“字符串”
test“字符串”<条件>“字符串”
[<条件>“字符串”>]
[“字符串”<条件>“字符串”]
其中条件可以是以下内容:
●=:
两个字符串是否相等。
●!
=:
两个字符串是否不相等。
●-z:
是否是空字符串。
●-n:
是否是非空字符串。
下面看几个字符串测试的例子。
●定义两个变量。
[root@srv~]#strA=“ctu”
[root@srv~]#strB=“dod”
●测试变量strA和strB的值是否相等。
在使用[]时,要注意[、]、变量及条件之间要使用空格分隔。
[root@srv~]#[$strA=$strB]
●显示上一个命令的返回值,非0表示不相等。
[root@srv~]#echo$?
1
●测试环境变量PPID是否为空。
[root@srv~]#[-z$PPID]
●显示上一个命令的返回值,非0表示为空。
[root@srv~]#echo$?
1
2.数值测试
虽然在bashShell中所有变量都是字符串,但如果变量值为字数还是可以进行数学运算的。
对于数值进行测试的方法如下。
test数值<条件>数值
[数值<条件>数值]
其中条件可以是以下内容:
●-eq:
数值相等。
●-ne:
数据不相等。
●-gt:
第一个数值大于第二个。
●-lt:
第一个数值小于第二个。
●-ge:
第一个数值大于等于第二个。
●-le:
第一个数值小于等于第二个。
下面看几个数值测试的例子。
●定义两个变量。
[root@srv~]#numA=10
[root@srv~]#numB=20
●测试变量numA和numB的值是否相等。
在使用[]时,要注意[、]、变量及条件之间要使用空格分隔。
[root@srv~]#[$numA-eq$numB]
●显示上一个命令的返回值,非0表示不相等。
[root@srv~]#echo$?
1
3.文件状态测试
在编写Shell脚本时经常需要对文件、目录进行特定属性的测试,对于文件、目录进行测试的方法如下。
test<条件>
[<条件>]
其中条件可以是以下内容:
●-d:
测试是否是目录。
●-e:
测试文件或目录是否存在。
●-f:
测试是否是文件。
●-L:
测试是否是符号链接。
●-r:
测试是否可读。
●-w:
测试文件是否可写。
●-x:
测试文件是否可以执行。
●-u:
测试文件是否有SUID。
●-g:
测试文件是否有SGID。
●-s:
测试文件长度大于0。
下面看几个文件测试的例子。
●测试“/etc”是否是一个目录。
[root@srv~]#[-d/etc]
●结果为0表示是一个目录。
[root@srv~]#echo$?
0
●测试当前用户对/etc/fstab文件是否有写权限。
[root@srv~]#[-w/etc/fstab]
●结果为0表示可写。
[root@srv~]#echo$?
0
●测试文件/etc/grub.conf是否是一个符号链接文件。
[root@srv~]#[-L/etc/grub.conf]
●结果为0表示是一个符号链接文件。
[root@srv~]#echo$?
0
4.逻辑操作符
在进行测试时经常会使用多个测试条件,这时可以使用逻辑操作符对多个测试条件进行逻辑运算,在bashShell中逻辑操作符包括:
“-a”逻辑与,指两边的条件都为真时结果才会真;“-o”逻辑或,两边条件任何一个为真时结果为真;“!
”逻辑否,条件为真时结果为假,条件为假时结果为真。
下面看几个逻辑操作符的例子。
●定义4个变量。
[root@srv~]#strA=“ctu”
[root@srv~]#strB=“CTU”
[root@srv~]#strC=“dod”
[root@srv~]#strD=“dod”
●测试条件$strA=$strB的结果是假(在bashShell中是区分大小写的)而测试条件$strC=$strD的结果是真。
对两个测试条件进行逻辑与。
[root@srv~]#[$strA=$strB-a$strC=$strD]
●测试结果为假。
[root@srv~]#echo$?
1
●对两个测试条件进行逻辑或。
[root@srv~]#[$strA=$strB-o$strC=$strD]
●测试结果为真。
[root@srv~]#echo$?
0
9.5.3流程控制
在一般情况下任何一种程序语言都是从上至下的顺序执行程序代码,bashShell也不例外。
同样,在bashShell中也可以通过判断和循环改变脚本的顺序执行。
1.判断结构
if、then、else语句提供条件测试,测试条件返回真(0)或假
(1)后,可相应执行一系列语句,其语法如下。
if<条件>;then
#当条件为真时执行的内容。
fi
-------------------------------------------------
if<条件>;then
#当条件为真时执行的内容。
else
#当条件为假时执行的内容。
fi
--------------------------------------------------
if<条件1>;then
#当条件1为真时执行的内容。
elif<条件2>;then
#当条件2为真时执行的内容。
else
#当条件1和条件2为假时执行的内容。
fi
if语句必须以fi终止,elif和else为可选项,如果语句中没有否则部分,那么就不需要elif和else部分。
if语句可以有许多elif部分,也可以嵌套使用。
下面看一个在脚本中使用if、then、else语句的例子,sh3.sh的作用是:
用户传一个目录名,当目录不存在进行则建立该目录,其中各行使用如下。
①:
将传入脚本的参数个数值赋给变量numN。
②:
如果numN为0,即没有传入参数,则显示“PleaseInputDirecotryName!
”。
③:
如果传入参数不止1个,则显示“TooManyParameter!
”。
④:
将传入脚本的第一个参数值赋给变量strI。
⑤:
如果变量strI所指的目录不存在,则建立一个目录。
[root@srv~]#catsh3.sh
#!
/bin/sh
numN=$#①
if[$numN-eq0];then②
echo“PleaseInputDirecotryName!
”
elif[$numN-gt1];then③
echo“TooManyParameter!
”
else
strI=$1④
if[!
-e$strI];then⑤
mkdir-p$strI
fi
fi
执行脚本sh3.sh。
[root@srv~]#./sh3.sh
PleaseInputDirecotryName!
[root@srv~]#./sh3.sh/usa/ctudod
TooManyParameter!
[root@srv~]#./sh3.sh/usa/ctu
[root@srv~]#ll/usa/ctu
total0
在bashShell中除了if判断结构以外还有case判断结构,case语句为多选择语句,可以使用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令,其语法如下。
case值in
模式1)
#当符合模式1时执行的内容。
;;
模式2)
#当符合模式2时执行的内容。
;;
...
;;
esac
case在匹配发现取值符合某一模式后,其间所有命令开始执行直至“;;”。
取值将检测匹配的每一个模式。
一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。
如果无一匹配模式,使用星号*捕获该值,再接受其他输入。
模式部分可能包括元字符,与在命令行文件扩展名例子中使用过的匹配模式类型相同,即:
“*”表示任意字符、“?
”表示任意单字符、“[..]”表示范围中任意字符。
下面看一个在脚本中使用case语句的例子,sh4.sh的作用:
要求用户输入一个1~3之间的数,如果输入正确则显示“youInput”及用户输入的内容,如果输入不正确则显示“youInput"$numI":
Thisisnotbetween1and3.”并退出,其中各行使用如下。
①:
echo语句默认情况下在显示内容后加自动加上换行,使用“-n”参数则不换行。
②:
read语句可以将用户输入的内容读取到指定的变量中。
[root@srv~]#catsh4.sh
#!
/bin/sh
echo-n“InputNumberfrom1to3:
”①
readnumI②
case$numIin
1)
echo“youInput1.”
;;
2)
echo“youInput2.”
;;
3)
echo“youInput2.”
;;
*)
echo“youInput“$numI”:
Thisisnotbetween1and3.”
exit1
;;
esac
执行脚本sh4.sh。
[root@srv~]#./sh4.sh
InputNumberfrom1to3:
1
youInput1.
[root@srv~]#./sh4.sh
InputNumberfrom1to3:
5
youInput5:
Thisisnotbetween1and3.
2.循环结构
循环是一系列命令的重复执行过程,在bashShell中支持三种类型的循环:
for循环,每次处理依次执行循环体内的内容,直至循环耗尽;until循环,直至条件为真前依次执行循环体内的内容;while循环,直至条件为假前依次执行循环体内的内容。
任何循环均可嵌套使用,如可以在一个for循环中嵌入另一个for循环。
while[条件]
do
循环体
done
----------------------------------------------------------
until[条件]
do
循环体
done
------------------------------------------------------
for((初始值;限制值;步长))
do
循环体
done
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- shell 脚本