在Shell脚本中执行使用if语句的好处是:能够根据特定的条件(eg:判断备份目录是否存在)来决定是否执行某项操做,当知足不一样的条件时执行 不一样的操做(eg:备份目录不存在则建立该目录,不然跳过操做)。该文将分别从条件测试操做,if语句结构,应用示例这三个方面讲解if语句在Shell 脚本中的应用。mysql
一、条件测试操做:sql
须要在Shell脚本中有选择性地执行任务时,首先面临的问题就是,如何设置命令执行的条件?编程
在Shell环境中,能够根据命令执行后返回状态值来判断该命令是否成功执行,当返回值为0是表示成功执行,不然(非0值)表示执行失败。用于特定条件表达式的测试时,可使用Linux系统中提供的专用工具——test命令、vim
使用test测试命令时,能够有如下两种形式。bash
test 条件表达式工具
【 条件表达式 】测试
这两种方式的做用彻底相同,但一般后一种形式更为经常使用,也更贴近编程习惯。须要注意的是,方括号“[”或者“]”与条件表达式语句之间至少须要有一个空格进行分隔。spa
根据须要判断的条件内容不一样,条件操做也不一样,最经常使用的条件主要包括文件状态测试,比较整数值大小,比较字符串,以及同时判断多个条件时的逻辑关系,下面将分别进行讲解。如下主要采用方括号的测试形式。.net
1.一、测试文件状态命令行
文件状态测试是指根据给定的路径名称,判断该名称对应的是文件仍是目录,或者判断文件是否可读,可写,可执行等。根据判断的状态不一样,在条件表达式中须要使用不一样的操做选项。
-d:测试是否为目录(Directory)。
-e:测试目录或文件是否存在(Exist)。
-f:测试是否为文件(File)。
-r:测试当前用户是否有权限读取(Read)。
-w:测试当前用户是否有权限写入(Write)。
-x:测试当前用户是否可执行(Excute)该文件。
-L:测试是否为符号链接(Link)文件。
执行条件测试操做之后,经过预约义变量“$?”能够得到测试命令的返回状态值,从而可以判断该条件是否成立(返回0值表示条件成立,非0值表示条件不成立)。但经过这种方式查看测试结果会比较繁琐。
例1:测试“/etc/hosts”是不是文件,并经过“$?”变量查看返回状态值,据此判断测试结果。
1
2
3
|
[ -f /etc/hosts ]
echo $?
0
//返回值为0,表示上一步测试的条件成立。
|
例2:测试“/media/cdrom/Server”及其父目录是否存在,若是存在则显示“YES”不然不输出任何信息。
1
2
3
4
|
[ -e /media/cdrom/Server ] && echo
"YES"
// 无输出表示该目录不 存在
[ -e /media/cdrom ] && echo
"YES"
YES
|
1.二、整数值 比较:
整数值比较是指根据给定的两个整数值,判断第一个数是否大于、等于、小于。。。。。。第2个数,可使用的操做选项以下:
1
2
3
4
5
6
|
-eq:第一个数等于(Equal)第二个数。
-ne:第一个数不等于(Not Equal)第二个数。
-gt:第一个数大于(Greater Than)第二个数。
-lt:第一个数小于(Lesser Than)第二个数。
-le:第一个数小于或等于(Lesser or Equal)第二个数。
-ge:第一个数大于或等于(Greater or Equal)第二个数。
|
整数值比较的测试操做在Shell脚本编写中的应用较多,如:用于判断磁盘使用率、登陆用户数量是否超标以及用于控制脚本语句的循环次数等。
例1:测试当前登陆到系统中的用户数量是否小于或等于10,是则输出”YES“。
1
2
3
4
|
who | wc -l
5
[ `who | wc -l` -le
10
] && echo ”YES"
YES
|
例2:提取出"/boot“分区的磁盘使用率,并判断是否超过95%(为了便于理解,操做步骤适当进行分解)
1
2
3
4
5
6
|
df -hT | grep ”/boot“ | awk
'{print $6}'
12
%
BootUsage=`df -hT | grep ”/boot
" | awk '{print $6}' | cut -d "
%" -f
1
`
echo $BootUsage
12
[ $BootUsage -gt
95
] && echo
"YES"
//无输出表示未超标
|
1.3:字符串比较:
字符串比较能够用于检查用户输入,如:在提供交互式操做时,判断用户输入的选项是否与指定的变量内容相匹配。“=”、“!=”操做选项分别表示匹配、不匹配。“-z”操做选项用于检查字符串是否为空。其中,“!”符号用于取反,表示相反的意思。
eg:提示用户输入一个文件路径,并判断是不是“/etc/inittab”,若是是则显示“YES”.
1
2
3
4
|
read -p
"Location: "
FilePath
Location: /etc/inittab
[ $FilePath =
"/etc/inittab"
] && echo
"YES"
YES
|
eg: 若当前环境变量LANG的内容不是“en.US”,则输出LANG变量的值,不然无输出。
1
2
|
[ $LANG !=
"en.US"
] && echo $LANG
zh_CN.UTF-
8
|
eg: 使用touch命令创建一个新文件,测试其内容是否为空,向文件中写入内容后,再次进行测试。
1
2
3
4
5
6
|
touch zero.file
[ -z `cat zero.file` ] && echo
"yes"
yes
echo
"something"
> zero.file
[ -z `cat zero.file` ] && echo yes
//无输出
|
1.4:逻辑测试:
逻辑测试是指同时使用的两个(或多个)条件表达式之间的关系。用户能够同时测试多个条件,根据这些条件是否同时成立或者只要有其中一个条件成立等状况,来决定采起何种操做。逻辑测试可使用的操做选项以下。
> &&:逻辑与,表示先后两个表达式都成立时整个测试结果才为真,不然结果为假。在使用test命令形式进程测试时,此选项能够改成" -a"。
> ||:逻辑或,表示先后两个条件至少有一个成立时整个测试结果即为真,不然结果为假。在使用test命令形式进行测试时,此选项能够改成"-o“。
> !:逻辑否,表示当指定的条件表达式不成立时,整个测试命令的结果为真。
在上述逻辑测试的操做选项中,”&&“和”||“一般也用于间隔不一样的命令操做,其做用是类似的。同时使用多个逻辑运算操做时,通常安装从左到右的顺序进行测试。
eg:测试当前的用户是不是teacher,若不是则提示”Not teacher“。
1
2
3
4
|
echo $USER
root
[ $USER = “teacher” ] || echo
"Not teacher"
Not teacher
|
eg:只要"/etc/rc.d/rc.local"或者"/etc/init.d/local'中有一个是文件,则显示"YES",不然无任何输出。
1
2
|
[ -f /etc/rc.d/rc.local ] || [ -f /etc/init.d/rc.local ] && echo "yes“
yes
|
eg:测试”/etc/profile“文件是否有可执行权限,若确实没有可执行权限,则提示”No x mode.“的信息。
1
2
|
[ ! -x ”/etc/profile
" ] && echo "
No x mode."
No x mode.
|
eg:若当前的用户是root且使用的Shell程序是"/bin/bash",则显示"YES“,不然无任何输出。
1
2
3
4
|
echo $USER $SHELL
root /bin/bash
[ $USER = ”root
" ] && [ $SHELL = "
/bin/bash
" ] && echo "
yes"
yes
|
2:if语句的结构:
前 面内容知道了一下条件测试操做,实际上使用"&&“和”||“逻辑测试能够完成简单的判断并执行相应的操做,可是当须要选择执行的命令语 句较多时,再使用这种方式将使命令行语句显得很复杂,难以阅读。而使用if语句,则能够更好地体现有选择性执行的程序结构,使得井井有条,清晰易懂。
if语句的选择结构由易到难能够分为三种类型,分别适用于不一样的应用场合。
2.一、单分支的if语句。
单分支的if语句是最简单的选择结构,这种结果只判断指定的条件,当”条件成立“时执行相应的操做,不然不作任何操做。单分支使用的语句格式以下。
if 条件测试命令
then
命令序列
fi
在上述语句中,首先经过判断条件测试命令的返回状态值是否为0(条件成立),若是是,则执行then后面的一条或多台可执行语句(命令序列),一直到fi为止表示结束,若是条件测试命令的返回值不为0(条件不成立),则直接去执行fi后面的语句。
2.二、双分支的if语句。
双分支的if语句使用了两路命令操做,在”条件成立‘、“条件不成立时分别执行不一样的命令序列”。双分支使用的语句格式以下:
if 条件测试命令
then
命令序列1;
else
命令序列2;
fi
在 上述语句中,首先经过if判断条件测试命令的返回状态值是否为0(条件成立),若是是,则执行then后面的一条或多条可执行语句(命令序列1),而后跳 转至fi结束判断,若是条件测试命令的返回状态值不为0(条件不成立),则执行else后面的语句,一直到fi表示结束。
2.三、多分支的if语句。
因为if语句能够根据条件测试命令的两种状态分别进行操做,因此可以嵌套使用,进行屡次判断(如:首先判断某学生的得分是否及格,如及格则再次判断是否高于90分。。。)多重分支使用的语句格式以下。
if 条件测试命令1
then
命令序列1
elif 条件测试命令2
then
命令序列2
else
命令序列3
fi
上面的语法格式中只嵌套了一个elif语句,实际上if语句中能够嵌套多个elif语句。if语句的嵌套在编写Shell脚本时并不经常使用,由于多重嵌套容易使程序结构变得复杂。须要使用多重分支程序结构时,更多的是使用case语句来实现。
eg:检查"/var/log/messages'文件是否存在,若存在则统计文件内容的行数并输出,不然不作任何操做。
1
2
3
4
5
6
7
|
vi chklog.sh
#!/bin/bash
LogFile=
"/var/log/messages"
if
[ -f $LogFile ] ; then
wc -l $LogFile
fi
sh chklog.sh
//sh是bash的符号连接
|
eg:提示用户指定备份目录的路径,若目录已存在则显示提示信息后跳过,不然显示相应提示信息后建立该目录。
1
2
3
4
5
6
7
8
9
|
[root@master ~]# vi mkbak.sh
#!/bin/bash
read -p
"What is your directory:"
Bakdir
if
[ -d $Bakdir ] ; then
echo
"$Bakdir already exist."
else
echo
"Bakdir is not exist,will make it."
mkdir $Bakdir
fi
|
eg:统计当前登陆到系统中的用户数量,并判断是否超过三个,如果则显示实际数量并给出警告信息,不然列出登陆的用户帐号成名及所在终端。
1
2
3
4
5
6
7
8
9
|
[root@localhost ~]# vim chkuser.sh
#!/bin/bash
UserNum=`who |wc -l`
if
[ $UserNum -gt
3
] ; then
echo
"Alert , too many login users ( Total: $UserNum )."
else
echo
"Login users:"
who | awk
'{print $1,$2}'
fi
|
eg:检 查portmap进程是否已经存在,若已经存在则输出“portmap service is running”;不然检查是否存在“/etc/rc.d/init.d/portmap”可执行脚本,存在则启动portmap服务,不然提示“no portmap script file.”。
1
2
3
4
5
6
7
8
9
10
11
|
[root@localhost ~]# vim chkportmap.sh
#!/bin/bash
pgrep portmap &> /dev/
null
if
[ $? -eq
0
]; then
echo
"protmap service is running."
elif
[ -x
"/etc/rc.d/init.d/portmap"
]; then
service portmap start
else
echo
"no portmap script file."
fi
|
eg:每隔五分钟监测一次mysqld服务程序的运行状态,若发现mysqld进程已终止,则在“/var/log/messages”文件中追加写入日志信息(包括当时时间),并重启mysqld服务,不然不进程任何操做。
1
2
3
4
5
6
7
8
9
10
|
vi chkmysql.sh
#!/bin/bash
service mysqld status &> /dev/
null
if
[ $? -ne
0
]; then
echo
"At time:`date`:Mysql Server is down."
>> /
var
/log/messages
service mysqld restart
fi
chmod u+x chkmysql.sh
crontab -e
*/
5
* * * * /root/chkmysql.sh
|
三、使用for魂环语句
在Shell脚本中使用for循环语句时,能够为变量设置一个取值列表,每次读取列表中不一样的变量值并执行相关命令操做,变量值用完之后则退出循环。Shell中的for语句不须要执行条件判断,其使用变量的取值来自于预先设置的值列表。
for语句结构:
for 变量名 in 取值列表
do
命令序列
done
在 上述语句中,使用in关键字为用户自定义变量设置了一个取值列表(以空格分隔的多个值),for语句第一次执行时首先将列表中的第一个取值赋给该变量。然 后执行do后边的命令序列;而后再将列表中的第二个取值赋给该变量,而后执行do后边的命令序列......如此循环,直到取值列表中的全部值都已经用 完,最后将跳至done语句,表示结束循环。
for语句示例:
eg:依次输出三条文件信息,包括一天中的"Morning"、"Noon"、"Evening"字串。
1
2
3
4
5
6
|
vi showday.sh
#!/bin/bash
for
TM
in
"Morning"
"Noon"
"Evening"
do
echo
"The $TM of the day."
done
|
eg:对于使用“/bin/bash”登陆Shell的系统用户,检查他们在"/opt"目录中拥有的子目录或文件数量,若是超过100个,则列出具体数量及对应的用户帐号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
vi chkfileown.sh
#!/bin/bash
DIR=
"/opt"
//设置检查的目标目录
LMT=
100
//设置文件数量的限制值
ValidUsers=`grep
"/bin/bash"
/etc/passwd | cut -d
":"
-f
1
`
//找出使用bash的系统用户列表
for
UserName
in
$ValidUsers
do
Num=`find $DIR -user $UserName | wc -l`
//统计每一个用户拥有的文件数
if
[ $Num -gt $LMT ] ; then
echo
"$UserName have $Num files."
fi
done
sh chkfileown.sh
root have
20998
files
|
四、使用while循环语句
在 Shell脚本中使用while循环语句时,将能够根据 特定的条件重复执行一个命令列表,直到该条件再也不知足时为至。除非有特别须要,不然在脚本程序中应该是避免出现无限循环执行命令的状况,由于若没法跳出循 环的话,后边的某些操做将没法执行。为了控制循环次数,一般会在执行的命令序列中包含修改测试条件的语句,当循环达到必定次数后,测试将再也不成立,从而可 以结束循环。
while语句的结构:
while 条件测试命令
do
命令序列
done
在 上述语句中,首先经过while判断条件测试命令的返回状态值是否为0(条件成立),若是是,则执行do后边的命令序列,而后返回到while再次进行条 件测试并判断返回状态值,若是条件仍然成立,则继续执行do后边的命令序列,而后返回到while重复条件测试......如此循环,直到所测试的条件不 成立时,跳转到done语句,表示结束循环。
使用while循环语句时,有两个特殊的条件测试返回值,即“true” (真)、"false"(假)。使用“true”做为测试条件时,条件将永远成立,循环体内的语句将无限次执行下去,反之使用“false”则条件永远不 成立,循环体内的语句将不会被执行,这两个特殊值也能够用在if语句的条件测试中。
while语句应用示例:
while语句能够用于须要重复操做的循环系统管理任务,并可以经过设置循环条件来灵活的实现各类管理任务。
eg:由用户从键盘输入一个大于1的整数(如50),并计算从1到该数之间各整数的和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[root@localhost ~]# vim sumint.sh
#!/bin/bash
read -p
"Input a number (>1):"
UP
i=
1
Sum=
0
while
[ $i -le $UP ]
do
Sum=`expr $Sum + $i`
i=`expr $i +
1
`
done
echo
"The sum of 1-$UP is : $Sum"
[root@localhost ~]# sh sumint.sh
Input a number (>
1
):
50
The sum of
1
-
50
is
:
1275
|
eg:批量添加20个系统用户帐号,用户名称依次为“stu1”、"stu2"、“stu3”、.......“stu20”,各用户的初始密码均设置为“123456”。
1
2
3
4
5
6
7
8
9
|
[root@localhost ~]# vim add20users.sh
#!/bin/bash
i=
1
while
[ $i -le
20
]
do
useradd stu$i
echo
"123456"
| passwd --stdin stu$i &> /dev/
null
i=`expr $i +
1
`
done
|
sh add20users.sh
eg:编写一个批量删除用户的脚本程序,将上面添加的20个用户删除。
1
2
3
4
5
6
7
8
|
[root@localhost ~]# vim del20users.sh
#!/bin/bash
i=
1
while
[ $i -le
20
]
do
userdel -r stu$i
i=`expr $i +
1
`
done
|
再次查看: cat /etc/passwd 就会发现那些用户再也不存在。
说了if、for 、while、语句后,就能够编写通常的系统管理任务脚本了,记得多多练习!其实除了这些Shell脚本语句外,还有好多好多,如:
case分支语句,until循环、shift移位,以及break和continue循环中断语句。你们能够查询!后续有时间我也会推出~