您的位置:首页 > 大数据 > 云计算

《云计算》Shell的基础应用(3)

2019-06-03 09:14 816 查看

1.使用for循环结构
问题
本案例要求编写一个Shell脚本chkhosts.sh,利用for循环来检测多个主机的存活状态,相关要求及说明如下:
待检测的多个目标IP地址,存放在ipadds.txt文件内
ping检测可参考前一天的pinghost.sh脚本
脚本能遍历ping各主机,并反馈存活状态
执行检测脚本以后,反馈结果如图-1所示。

图-1
方案
在Shell脚本应用中,常见的for循环采用遍历式、列表式的执行流程,通过指定变量从值列表中循环赋值,每次复制后执行固定的一组操作。
for循环的语法结构如下所示:
for 变量名 in 值列表
do
命令序列
done
步骤
实现此案例需要按照如下步骤进行。
步骤一:练习for循环基本用法
脚本1,循环输出“我来自 XX 。”,其中XX替换为指定的几个城市名:
[root@svr5 ~]# vim for01.sh
#!/bin/bash
for i in “北京” “上海” “长沙” “香港” “台湾”
do
echo “我来自 $i 。”
done
[root@svr5 ~]# chmod +x for01.sh
脚本1的运行结果测试:
[root@svr5 ~]# ./for01.sh
我来自 北京 。
我来自 上海 。
我来自 长沙 。
我来自 香港 。
我来自 台湾 。
脚本2,列出Yum库中vsftpd、bind、httpd、mysql-server四个软件包的摘要描述信息(Summary行的描述文本):
[root@svr5 ~]# vim for02.sh
#!/bin/bash
for i in “vsftpd” “bind” “httpd” “mysql-server”
do
yum info KaTeX parse error: Expected 'EOF', got '#' at position 39: …e [root@svr5 ~]#̲ chmod +x for02…(cat /root/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo “Host $IP is up.”
else
echo “Host $IP is down.”
fi
done

[root@svr5 ~]# chmod +x chkhosts.sh
4)测试、验证脚本
[root@svr5 ~]# ./chkhosts.sh
Host 192.168.4.5 is up.
Host 192.168.4.205 is up.
Host 172.16.16.78 is down.
Host 202.106.178.234 is down.
2.使用while循环结构
问题
本案例要求编写三个使用while循环的脚本程序,分别实现以下目标:
批量添加用户账号:stu1-stu20
批量删除用户账号:stu1-stu20
检测192.168.4.0/24网段,列出不在线的主机地址
方案
while循环属于条件式的执行流程,会反复判断指定的测试条件,只要条件成立即执行固定的一组操作,直到条件变化为不成立为止。所以while循环的条件一般通过变量来进行控制,在循环体内对变量值做相应改变,以便在适当的时候退出,避免陷入死循环。
while循环的语法结构如下所示:
while 条件测试
do
命令序列
done
步骤
实现此案例需要按照如下步骤进行。
步骤一:批量添加用户账号stu1-stu20
添加的账号有固定的前缀stu(练习中可自行设置),多个账号从1开始编号,比如stu1、stu2、stu3、……、stu20。—— 编写脚本uaddwhile.sh,实现批量添加这20个用户账号的功能,密码均设为123456。
脚本编写参考如下:
[root@svr5 ~]# vim uaddwhile.sh
#!/bin/bash
PREFIX=“stu” //定义用户名前缀
i=1
while [ $i -le 20 ]
do
useradd PREFIX{PREFIX}PREFIXi //添加的用户名为:前缀+编号
echo “123456” | passwd --stdin PREFIX{PREFIX}PREFIXi &> /dev/null
let i++
done
[root@svr5 ~]# chmod +x uaddwhile.sh
执行脚本并验证结果:
[root@svr5 ~]# ./uaddwhile.sh
[root@svr5 ~]# grep ^stu /etc/passwd //检查添加的用户
stu1❌531:531::/home/stu1:/bin/bash
stu2❌532:532::/home/stu2:/bin/bash
stu3❌533:533::/home/stu3:/bin/bash
stu4❌534:534::/home/stu4:/bin/bash
stu5❌535:535::/home/stu5:/bin/bash
stu6❌536:536::/home/stu6:/bin/bash
stu7❌537:537::/home/stu7:/bin/bash
stu8❌538:538::/home/stu8:/bin/bash
stu9❌539:539::/home/stu9:/bin/bash
stu10❌540:540::/home/stu10:/bin/bash
stu11❌541:541::/home/stu11:/bin/bash
stu12❌542:542::/home/stu12:/bin/bash
stu13❌543:543::/home/stu13:/bin/bash
stu14❌544:544::/home/stu14:/bin/bash
stu15❌545:545::/home/stu15:/bin/bash
stu16❌546:546::/home/stu16:/bin/bash
stu17❌547:547::/home/stu17:/bin/bash
stu18❌548:548::/home/stu18:/bin/bash
stu19❌549:549::/home/stu19:/bin/bash
stu20❌550:550::/home/stu20:/bin/bash
步骤二:批量删除用户账号stu1-stu20
针对前面执行uaddwhile.sh脚本批量添加的用户账号,再建立一个批量删除这些账号的脚本udelwhile.sh。结构类似,只要替换为删除相关的操作即可。
脚本编写参考如下:
[root@svr5 ~]# vim udelwhile.sh
#!/bin/bash
PREFIX=“stu”
i=1
while [ $i -le 20 ]
do
userdel -r PREFIX{PREFIX}PREFIXi &> /dev/null
let i++
done
[root@svr5 ~]# chmod +x udelwhile.sh
执行脚本并验证结果:
[root@svr5 ~]# ./udelwhile.sh
[root@svr5 ~]# grep ^stu /etc/passwd //再检查已无相应账号信息
[root@svr5 ~]#
步骤三:检测192.168.4.0/24网段,列出不在线的主机地址
1)任务需求及思路分析
要求的是“检测192.168.4.0/24网段,列出不在线的主机地址”。
检测目标是一个网段,其网络部分“192.168.4.”可以作为固定的前缀;而主机部分包括从1~254连续的地址,所以可结合while循环和自增变量进行控制。
检测方法仍然采用ping,参考此前的主机检测脚本。
2)根据实现思路编写脚本
[root@svr5 ~]# vim chknet.sh
#!/bin/bash
NET=“192.168.4.”
i=1
while [ i−le254]doIP="i -le 254 ] do IP="i−le254]doIP="{NET}$i"
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo “Host $IP is up.”
else
echo “Host $IP is down.”
fi
let i++
done
[root@svr5 ~]# chmod +x chknet.sh
3)测试、验证脚本
[root@svr5 ~]# ./chknet.sh
Host 192.168.4.1 is down.
Host 192.168.4.2 is down.
Host 192.168.4.3 is down.
Host 192.168.4.4 is down.
Host 192.168.4.5 is up.
… …
Host 192.168.4.250 is down.
Host 192.168.4.251 is down.
Host 192.168.4.252 is down.
Host 192.168.4.253 is down.
Host 192.168.4.254 is down.
3.基于case分支编写服务脚本
问题
本案例要求编写myprog服务脚本,相关要求如下:
能支持start、stop、restart等控制参数
控制参数通过位置变量$1传入
能通过chkconfig命令来管理此服务
服务操作为sleep进程的开启/关闭/重启
方案
case分支属于匹配执行的方式,它针对指定的变量预先设置一个可能的取值,判断该变量的实际取值是否与预设的某一个值相匹配,如果匹配上了,就执行相应的一组操作,如果没有任何值能够匹配,就执行预先设置的默认操作。
case分支的语法结构如下所示:
case 变量值 in
模式1)
命令序列1 ;;
模式2)
命令序列2 ;;
… …
*)
默认命令序列
Esac
Linux系统的服务脚本默认均位于/etc/init.d/目录下,基本上都采用了case分支结构来识别控制参数。能够执行“/etc/init.d/服务名 start”或“service 服务名 start”来启动对应的服务,是因为对应的脚本文件能够处理“start”这个位置参数。
以network服务脚本为例,可以看一下它的case结构是怎样的(此处暂忽略其它无关语句):
[root@svr5 ~]# vim /etc/init.d/network
#! /bin/bash

network Bring up/down networking

chkconfig: 2345 10 90 //管理参数(自启的运行级别 开启顺序 关闭顺序)

description: Activates/Deactivates all network interfaces configured to \

start at boot time. //服务描述

… …
case “$1” in //检查执行时的第1个位置参数
start) //若参数是“start”,启用各种网络设备及相关进程
… … //一系列启用操作
;;
stop) //若参数是“stop”,停用各种网络设备及相关进程
… … //一系列停用操作
;;
status) //若参数是“status”,报告网络接口状态
echo $“Configured devices:”
echo lo $interfaces
echo $“Currently active devices:”
echo $(/sbin/ip -o link show up | awk -F “: " '{ print KaTeX parse error: Expected 'EOF', got '}' at position 3: 2 }̲') ;; …CWD”
$0 stop //调用本脚本,通过stop参数先停止服务
$0 start //调用本脚本,通过start参数再启用服务
;;
*) //若参数无法识别,则给出正确的用法帮助,并退出脚本
echo $“Usage: $0 {start|stop|restart|reload|status}”
exit 1
esac
比如,当尝试给network脚本提供check参数时,会提示正确的用法:
[root@svr5 ~]# /etc/init.d/network check
Usage:/etc/init.d/network {start|stop|restart|reload|status}
或者
[root@svr5 ~]# service network check
Usage:/etc/init.d/network {start|stop|restart|reload|status}
步骤
实现此案例需要按照如下步骤进行。
步骤一:任务需求及思路分析
要将myprog作为系统服务,应该将脚本复制到/etc/init.d/目录下。若希望通过chkconfig来进行管理,还需要在脚本开头添加chkconfig管理参数、服务描述。
服务脚本通过case分支检查位置参数 $1 ,根据参数的不同取值做不同操作。
响应start的操作是启用一个sleep进程(只是测试嘛,就别加太复杂的语句啦),比如sleep 7200 &可在后台睡眠2小时。
响应stop的操作可简单使用pkill等命令杀死已启用的sleep进程。
响应status的操作(可选)则可通过pgrep等命令来检索sleep进程、报告 1e378 结果。
响应restart的操作则依次调用前面的stop、start即可。
对于其他未知参数,一律提示正确用法。
步骤二:根据实现思路编写脚本文件
脚本编写参考如下,其中echo命令的-n选项表示不输出末尾的换行符:
[root@svr5 ~]# vim /etc/init.d/myprog
#!/bin/bash

chkconfig: 2345 90 10

description: Startup script for sleep Server. (for Test only)

case “$1” in
start)
echo -n "正在启动sleep服务 … "
if sleep 7200 & //启动sleep进程,若成功则显示OK
then
echo “OK”
fi
;;
stop)
echo -n "正在停止sleep服务 … "
pkill “sleep” &> /dev/null && echo “OK” //结束sleep进程
;;
status)
if pgrep “sleep” &>/dev/null //检查sleep进程状态,报告结果
then
echo “sleep服务已经启动。”
else
echo “sleep服务已经停止。”
fi
;;
restart)
$0 stop //先停止本服务
$0 start //再启动本服务
;;
*) //默认输出脚本用法
echo “用法: $0 {start|stop|status|restart}”
exit 1
esac

[root@svr5 ~]# chmod +x /etc/init.d/myprog
步骤三:验证、测试脚本
未提供参数,或提供的参数无法识别时,提示正确用法:
[root@svr5 ~]# /etc/init.d/myprog
用法: /etc/init.d/myprog {start|stop|status|restart}
[root@svr5 ~]# /etc/init.d/myprog check
用法: /etc/init.d/myprog {start|stop|status|restart}
通过service调用的效果也是相同的:
[root@svr5 ~]# service myprog check
用法: /etc/init.d/myprog {start|stop|status|restart}
确认可响应status控制参数:
[root@svr5 ~]# service myprog status
sleep服务已经停止。
确认可响应start控制参数,再次检查服务状态:
[root@svr5 ~]# service myprog start
正在启动sleep服务 … OK
[root@svr5 ~]# service myprog status
sleep服务已经启动。
确认可响应stop控制参数,再次检查服务状态:
[root@svr5 ~]# service myprog stop
正在停止sleep服务 … OK
[root@svr5 ~]# service myprog status
sleep服务已经停止。
重新启动myprog服务,再确认可响应restart控制参数:
[root@svr5 ~]# service myprog start
正在启动sleep服务 … OK
[root@svr5 ~]# service myprog restart
正在停止sleep服务 … OK
正在启动sleep服务 … OK
上述操作完成后,说明此服务脚本基本上可以使用了。
步骤四:添加myprog服务
通过将服务提交给chkconfig管理,方便配置在不同运行级别是否自动运行。
仅仅将脚本文件复制到/etc/init.d/目录下,通过chkconfig工具是看不到的,但如果脚本中配置了管理参数,则会在–list时给出相应提示:
[root@svr5 ~]# chkconfig --list myprog
myprog 服务支持 chkconfig,但它在任何级别中都没有被引用(运行“chkconfig --add myprog”)
执行以下操作将myprog添加为系统服务,并再次检查自启状态:
[root@svr5 ~]# chkconfig --add myprog //添加myprog服务
[root@svr5 ~]# chkconfig --list myprog //确认添加结果
myprog 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
此后,就可以使用chkconfig工具来调整myprog服务的自启状态了。比如,以下操作可以将所有自启关闭:
[root@svr5 ~]# chkconfig myprog off //将自启设为关闭
[root@svr5 ~]# chkconfig --list myprog //确认设置结果
myprog 0:关闭 1:关闭 2:关闭 3:关闭 4:关闭 5:关闭 6:关闭
yhttpd 0:关闭 1:关闭 2:关闭 3:关闭 4:关闭 5:关闭 6:关闭
如果已经有其他关于httpd服务的自启脚本,这里建议就不要将myhttpd也设为自动开启了,否则会出现端口冲突等故障。
5.脚本退出及参数迁移
问题
本案例要求编写两个Shell脚本,相关要求如下:
整数检测脚本chkint.sh:能够检查从键盘键入的值,如果是整数(利用expr运算的返回值来检测)则显示输入的整数结果,否则报错退出
整数求和脚本mysum.sh:整数值以位置参数提供,个数不定
方案
由于Shell默认不支持小数运算,因此可以利用expr对提供的整数值进行运算,若执行报错,则说明提供的值不合法。比如:
[root@svr5 ~]# X=1234 //整数值变量
[root@svr5 ~]# expr $X + 1 //正常参与运算
1235
[root@svr5 ~]# echo $? //执行状态正常
0
[root@svr5 ~]# X=abc //非整数变量
[root@svr5 ~]# expr $X + 1 //运算时报错
expr: 参数数目错误
[root@svr5 ~]# echo $? //执行状态异常
2
shift操作用来迁移位置变量,比如执行 ./mysum.sh 10 20 30操作,则对于脚本mysum.sh来说,第一个位置变量$1的值为10、第二个位置变量$2的值为20、第三个位置变量$3的值为30。
若在脚本mysum.sh中执行一次shift操作,则$1的值变为20、$2的值变为30、$3的值为空。
再执行一次shift操作,则$1的值变为30、$2和$3的值都为空。
再执行一次shift操作,则$1、$2、$3的值都为空,相当于所有位置参数都丢弃了,位置参数的总个数为0。
步骤
实现此案例需要按照如下步骤进行。
步骤一:编写脚本chkint.sh
1)编写脚本文件
[root@svr5 ~]# vim chkint.sh
#!/bin/bash
read -p “请输入一个整数:” NUM
if expr KaTeX parse error: Expected 'EOF', got '&' at position 9: NUM + 1 &̲> /dev/null the…NUM"
else
echo “您输入的不是整数,请重新执行本程序。”
exit 10
fi

[root@svr5 ~]# chmod +x chkint.sh
2)测试脚本执行效果
[root@svr5 ~]# ./chkint.sh
请输入一个整数:1234
您输入的整数是:1234
[root@svr5 ~]# ./chkint.sh
请输入一个整数:12.34
您输入的不是整数,请重新执行本程序。
步骤二:编写mysum.sh脚本文件
1)编写脚本文件
[root@svr5 ~]# vim mysum.sh
#!/bin/bash
SUM=0
while [ KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲ -gt 0 ] do …SUM+$1
shift
done
echo “The SUM is : $SUM”

[root@svr5 ~]# chmod +x mysum.sh
2)测试脚本执行效果
[root@svr5 ~]# ./mysum.sh 10 20 30
The SUM is : 60
[root@svr5 ~]# ./mysum.sh 12 34 56 78
The SUM is : 180
[root@svr5 ~]# ./mysum.sh 111 222 333 444 555
The SUM is : 1665

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: