4、流程控制语句和函数
•4.1 条件语句
•简单的shell脚本从头到尾可以执行命令的集合,而条件语句允许用户在shell脚本中实现当满足条件时执行。
•包括if/then,if/then/else,if/then/elif/then/else,case语句等。
if/then语句语法结构:
if <条件>;then
<命令1>
<命令2>
……
fi
示例:
systemctl is-active psacct >/dev/null
if [ $? –ne 0 ];then
systemctl start psacct
fi
shell程序中的条件分支是通过if条件语句来实现的,其一般格式为:
if条件命令串
then
条件为真时的命令串
else
条件为假时的命令串
fi
If语句语法(bash和pdksh)
if (表达式1) then
命令
elif (表达式2) then
命令
else
命令
fi
elif和else条件语句都是if语句的可选部分,elif是else if的缩写。
If语句语法(tcsh)
if (表达式1) then
命令
else if (表达式2) then
命令
else
命令
endif
举例:
if [-f .profile]
then
echo “there is a .profile file in the current directory.”
else
echo “could not find the .profile file.”
fi
if/then/else语句:
语法结构:
if/then/else语句
if <条件>;then
<命令1>
else
<命令2>
fi
if/then/elif/then/else语句:
(继续扩展,用于测试多个条件)
语法结构:
if <条件1>;then
<命令1>
elif<条件2>; then
<命令2>
else
<命令3>
fi
示例1:
systemctl is-active psacct >/dev/null
if [ $? –ne 0 ];then
systemctl start psacct
else
systemctl stop psacct
fi
示例2:
systemctl is-active httpd >/dev/null
HTTPD_ACTIVE=$?
systemctl is-active mariadb >/dev/null
MARIADB_ACTIVE=$?
if [ “$HTTPD_ACTIVE” –eq 0 ];then
systemctl start httpd
elif [ “$MARIADB_ACTIVE” –eq 0 ];then
systemctl start mariadb
else
echo “the httpd and mariadb is error”
fi
case语句
if/then/elif/then/else语句可以添加任意需要的条件去执行,但随着条件的增加,逻辑结构复杂不易理解,因此可以使用case语句。
语法结构:
case <变量> in
<值1>)
命令1
;;
<值2>)
命令2
;;
esac
if条件语句用于在两个选项中选定一项,而case条件选择为用户提供了根据字符串或变量的值从多个选项中选择一项的方法。
shell通过计算字符串string的值,将其结果依次和表达式exp-1、exp-2等进行比较,直到找到一个匹配的表达式为止,如果找到了匹配项则执行它下面的命令直到遇到一对分号(;;)为止。
在case表达式中也可以使用shell的通配符(“*”、“?”、“[ ]”)。通常用“*”作为case命令的最后表达式以便使在前面找不到任何相应的匹配项时执行“其他命令行”的命令。
举例:
此代码检查第一个命令行选项是-i还是-e。如果是-i,程序开始对以字母-i开头的第2个命令行选项所定义的文件中的行数进行计数。如果是-e,程序开始对以字母-e开头的第2个命令行选项所定义的文件中的行数进行计数。如果第1个命令行选项不是-e或-i,程序显示错误。
case $1 in
-i)
count=‘grep ^i $2 | wc -l’
echo “The number of lines in $2 that start with an I is $count”
;;
-e)
count=‘grep ^e $2 | wc -l’
echo “The number of lines in $2 that start with an e is $count”
;;
* )
echo “That option is not recognized”
;;
esac
case语句示例:
case “$1” in
start)
start
;;
stop)
stop
;;
*)
echo “Usage:$0(start|stop)”
esac
•4.2 for循环语句
管理员在日常运维过程中,常常会遇到重复的任务,可能表现为对目标多次执行某个操作,比如10分钟内,每隔1分钟检查进程有无完成,也可能表现为一次对多个目标执行,那么此时用循环语句是合适的,其中for循环就是常见的一种循环结构。
for循环语法结构:
for<变量> in <取值列表>;do
<命令1>
<命令2>
……
done
for循环的一般格式为(bash和pkdsh):
for 变量名
[in数值列表]
do
若干个命令行
done
变量名可以是用户选择的任何字符串,如果变量名是var,则在in之后给出的数值将顺序替换循环命令列表中的$var。如果省略了in,则变量var的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。
在tcsh中,与for语句相同的是foreach语句,其一般格式为:
foreach name (列表)
命令
end
实例
将任意数量的文本文件作为命令行选项。执行时,程序读取各个文件,将所有字符转换成大写,然后将结果存储在文件名相同而扩展名为.caps的文件中。
for file
do
tr a-z A-Z < $file> $file.caps
done
示例1:
for HOST in host1 host2 host3;do
echo “$HOST”
done
示例2:
for PACKAGE in $(rpm –qa kernel);do
echo “$PACKAGE”was installed
done
•4.3 函数
在shell脚本中,函数是一种隔离代码段的的方法,如果某个代码段经常需要被重复调用,可以使用函数实现,如代码需要更新,只需更新函数内容即可,所有引用函数的位置都会执行更新后的代码。
函数示例:
pathmunge ( ) {
if [ “$2” = “after”];then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
}
函数定义
在shell中还可以定义函数。函数实际上也是由若干条shell命令组成的,因此它与shell程序形式上是相似的,不同的是它不是一个单独的进程,而是shell程序的一部分。函数定义的基本格式为:
functionname( )
{
若干命令行
}
调用函数的格式为:
functionname [param1 param2……]
shell函数可以完成某些例行的工作,而且还可以有自己的退出状态,因此函数也可以作为if、while等控制结构的条件。
在函数定义时不用带参数说明,但在调用函数时可以带有参数,此时shell将把这些参数分别赋予相应的位置参数$1、$2、...及$*。
实例:
upper() {
shift
for I
do
tr a-z A-Z < $1 >$1.out
rm $1
mv $1.out $1
shift
done;
}
lower() {
shift
for I
do
tr A-Z a-z < $1 > $1.out
rm $1
mv $1.out $1
shift
done;
}
if [ “$EUID” = “0”];then
pathmunge /sbin
pathmunge /usr/sbin
pathmunge /usr/local/sbin
else
pathmunge /usr/local/sbin after
pathmunge /usr/sbin after
pathmunge /sbin after
fi