本案例要求参考PPT上的示例,分别练习以下条件测试操作:
实现此案例需要按照如下步骤进行。
步骤一:条件测试的基本用法
1)语法格式
使用“test 表达式”或者[ 表达式 ]都可以,注意空格不要缺少。
条件测试操作本身不显示出任何信息。所以可以在测试后查看变量$?的值来做出判断。
步骤二:字符串测试
1)== 比较两个字符串是否相同
检查当前用户是否为root。
当root用户执行时:
[root@svr5 ~]# [ $USER == "root" ] #测试
[root@svr5 ~]# echo $? #查看结果0为对,非0为错
当普通用户执行时:
[zengye@svr5 ~]$ [ $USER == "root" ]
[zengye@svr5 ~]$ echo $? #查看结果0为对,非0为错
2)!= 比较两个字符串是否不相同
当普通用户执行时:
[zengye@svr5 ~]$ [ $USER != "root" ]
当root用户执行时:
[root@svr5 ~]# [ $USER != "root" ]
3)变量为空时:
[ "$c" == abc ] #如果变量为空,有可能报错,加双引号可以避免
[ -z $c ] #判断变量是否为空
[ ! -z $c ] #判断变量是否非空
还有一个-n可以测试变量是否不为空(相当于! -z)。
或者结合&&、||等逻辑操作显示出结果 。
4)一行执行多条命令的情况
# A && B #仅当A命令执行成功,才执行B命令
# A || B #仅当A命令执行失败,才执行B命令
# A ; B #执行A命令后执行B命令,两者没有逻辑关系
步骤三:多个条件/操作的逻辑组合
1)&&,逻辑与
给定条件必须都成立,整个测试结果才为真。
检查变量X的值是否大于10,且小于30:
[root@svr5 ~]# X=20 #设置X变量的值为20
[root@svr5 ~]# [ $X -gt 10 ] && [ $X -lt 30 ] && echo "YES"
2)||,逻辑或
只要其中一个条件成立,则整个测试结果为真。
只要/tmp/、/var/spool/目录中有一个可写,则条件成立:
[root@svr5 ~]# [ -w "/tmp/" ] || [ -w "/var/spool/" ] && echo "OK"
还可以按以下方式理解与测试
A && B A、B任务都成功算真
A || B A、B 任务有一个成功算真
touch a b c
ls a && ls b && ls c #结果是都显示
ls a || ls b || ls c #结果是显示a
ls a && ls b || ls c #结果是显示a和b
ls a || ls b && ls c #结果是显示a和c
[ root != $USER ] && echo "非管理员不能执行该脚本" && exit
步骤四:整数值比较
参与比较的必须是整数(可以调用变量)
1)-eq 比较两个数是否相等。
[root@svr5 ~]# X=20 #定义一个测试变量
[root@svr5 ~]# [ $X -eq 20 ] && echo "yes" || echo "no"
2)-ne 比较两个数是否不相等。
[root@svr5 ~]# [ $X -ne 20 ] && echo "yes" || echo "no"
3)-gt 比较前面的整数是否大于后面的整数。
[root@svr5 ~]# [ $X -gt 10 ] && echo "yes" || echo "no"
4)-ge 比较前面的整数是否大于或等于后面的整数。
[root@svr5 ~]# [ $X -ge 10 ] && echo "yes" || echo "no"
5)-lt 比较前面的整数是否小于后面的整数。
[root@svr5 ~]# [ $X -lt 10 ] && echo "yes" || echo "no"
6)-le 比较前面的整数是否小于或等于后面的整数。
[root@svr5 ~]# [ $X -le 10 ] && echo "yes" || echo "no"
编写脚本,每2分钟检查服务器的用户数量,如果发生变化则发邮件通知管理员
准备环境:
yum -y install mailx postfix #安装邮件客户端软件和服务端程序
systemctl restart postfix #启动邮件服务
echo "测试" | mail -s test root #编写脚本前,测试下邮件功能是否正常 ,mail -s是发送邮件,test是标题,root是给谁发,echo后面写要发送的邮件内容,如果邮件太多可以删除/var/spool/mail/root文件清空邮箱
编写脚本:
#!/bin/bash
x=$(cat /etc/passwd | wc -l) #将目前用户数量赋值给变量x
[ $x -gt 29 ] && echo "用户数量发生变化,服务器可能被入 侵" | mail -s test root #如果目前用户数量大于29,就发邮件给管理员,29是之前查看的用户数量
然后测试,以下命令不是脚本内容,要在命令行中敲,不写在脚本中
chmod u+x test01.sh #然后给脚本加x权限
crontab -e #编写计划任务
*/2 * * * * /opt/test01.sh #定义每2分钟执行脚本
步骤五:识别文件/目录的状态
1)-e 判断对象是否存在(不管是目录还是文件)
[root@svr5 ~]# [ -e "/opt/a" ] && echo "yes" || echo "no"
2)-d 判断对象是否为目录(存在且是目录)
[root@svr5 ~]# [ -d "/opt/b" ] && echo "yes" || echo "no"
3)-f 判断对象是否为文件(存在且是文件)
[root@svr5 ~]# [ -f "/opt/c" ] && echo "yes" || echo "no"
4)-r 判断对象是否可读
[root@svr5 ~]# [ -r "/opt/a" ] && echo "yes" || echo "no"
5)-w 判断对象是否可写
[root@svr5 ~]# [ -w "/opt/a" ] && echo "yes" || echo "no"
6)-x 判断对象是否具有x权限
[root@svr5 ~]# [ -x "/opt/a" ] && echo "yes" || echo "no"
注意:-r与-w对root无效
本案例要求编写3个Shell脚本,分别实现以下目标:
if单分支的语法组成:
if 条件测试;then
命令序列
fi
if双分支的语法组成:
if 条件测试;then
命令序列1
else
命令序列2
fi
if多分支的语法组成:
if 条件测试1 ;then
命令序列1
elif 条件测试2 ;then
命令序列2
else
命令序列n
fi
实现此案例需要按照如下步骤进行。
步骤一:检测/if_test/cdrom目录,若不存在则创建
1)编写脚本如下:
[root@svr5 ~]# vim dir.sh
#!/bin/bash
dir="/if_test/cdrom/"
if [ ! -d $dir ];then
mkdir -p $dir
fi
[root@svr5 ~]# chmod +x dir.sh #添加可执行权限
步骤二:使用if双分支
#!/bin/bash
if [ $UID -eq 0 ];then
echo "我是管理员"
echo ok
else
echo "我不是管理员"
echo no
fi
编写脚本,检测并判断指定的主机是否可ping通
1)分析任务需求
使用ping命令检测目标主机时,可通过$?来判断ping目标主机的成败。
为了节省ping测试时间,可以只发送3个测试包(-c 3)、缩短发送测试包的间隔秒数(-i 0.2)、等待反馈的超时秒数(-W 1)。比如,检查可ping通的主机:
[root@svr5 ~]# ping -c 3 -i 0.2 -W 1 192.168.88.5
[root@svr5 ~]# echo $? #执行状态表示成功
0
2)脚本编写参考如下:
[root@svr5 ~]# vim pinghost.sh
#!/bin/bash
ping -c 3 -i 0.2 -W 1 $1 &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $1 is up."
else
echo "Host $1 is down."
fi
[root@svr5 ~]# chmod +x pinghost.sh
3)测试、验证脚本功能
[root@svr5 ~]# ./pinghost.sh 192.168.88.5
Host 192.168.88.5 is up.
[root@svr5 ~]# ./pinghost.sh 192.168.88.50
Host 192.168.88.50 is down.
步骤三:从键盘读取一个数值,按情况给出不同结果
1)脚本编写参考如下:
#!/bin/bash
read -p "询问内容" x
if 条件;then
echo "情况一"
elif 条件;then
echo "情况二"
elif 条件;then
echo "情况三"
else
echo "情况四"
fi
本案例要求编写一个Shell脚本chkhosts.sh,利用for循环来检测多个主机的存活状态
使用for循环,语法结构如下所示:
for 变量名 in 值1 值2 值3 #值的数量决定循环任务的次数
do
命令序列
done
实现此案例需要按照如下步骤进行。
步骤一:练习for循环基本用法
通过循环批量显示5个hello world:
[root@svr5 ~]# vim for01.sh
#!/bin/bash
for i in 1 2 3 4 5
do
echo "hello world"
done
通过循环批量显示10个abc:
[root@svr5 ~]# vim for02.sh
#!/bin/bash
for i in {1..10}
do
echo "abc"
done
通过循环批量显示10个数字:
[root@svr5 ~]# vim for03.sh
#!/bin/bash
for i in {1..10}
do
echo "$i"
done
a=10
for i in `seq $a` #如果循环次数是通过变量决定可以用seq指令
do
echo "$i"
done
编写脚本,批量创建账户
#!/bin/bash
for i in $(cat /opt/name.txt) #循环批量创建name.txt里面所有账户,文档中每行是一个名字,该文档要提前创建,与脚本在同一目录下即可
do
useradd $i
done
步骤二:批量检测多个主机的存活状态
1)编写脚本如下:
[root@svr5 ~]# vim chkhosts.sh
#!/bin/bash
for i in {1..10}
do
ping -c 3 -i 0.2 -W 1 192.168.88.$i &> /dev/null
if [ $? -eq 0 ] ; then
echo "88.$i is up."
else
echo "88.$i is down."
fi
done
思考,如何最后输出up与down 的总数?
附加扩展知识(C语言风格的for循环语法格式)
[root@svr5 ~]# vim cfor.sh
#!/bin/bash
for ((i=1;i<=5;i++))
do
echo $i
done
while循环属于条件式的执行流程,会反复判断指定的测试条件,只要条件成立即执行固定的一组操作,直到条件变化为不成立为止。所以while循环的条件一般通过变量来进行控制,在循环体内对变量值做相应改变,以便在适当的时候退出,避免陷入死循环。
使用while循环,语法结构如下所示:
while 条件测试 #根据条件的结果决定是否要执行任务,条件测试成功的话就执行,如果失败立刻结束循环
do
命令序列
done
练习while循环基本用法
脚本1,无心的死循环脚本:
[root@svr5 ~]# vim while01.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo "abc"
done
[root@svr5 ~]# chmod +x while01.sh
[root@svr5 ~]# ./while01.sh #死循环,需要使用Ctrl+C终止脚本
脚本2,死循环的一般格式:
[root@svr5 ~]# vim while02.sh
#!/bin/bash
while : #冒号可以表示条件为真
do
echo "abc"
sleep 0.1 #休息0.1秒
done
[root@svr5 ~]# chmod +x while02.sh
[root@svr5 ~]# ./while02.sh #死循环,需要使用Ctrl+C终止脚本
脚本3,有效循环脚本:
[root@svr5 ~]# vim while03.sh
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo "$i"
let i++
done