返回顶部

zhangfd

个人博客,仅供学习使用

导航

shell编程 11 --- for 和 select 循环语句的应用实践

shell编程 11 --- for和select循环语句的应用实践


for循环语句和while循环语句类似,但for循环语句主要用于执行次数有限的循环,
而不是用于守护进程及无限循环。for循环语句常见的语法有两种。


11.1 for循环语句结构

第一种for循环语句为变量取值型,语法结构如下:

for 变量名 in 变量取值列表
do
	指令...
done
# 在此结构中“in变量取值列表”可以省略,省略时相当于in“$@”,
# 也就是使用for i就相当于使用for i in“$@”。

在这种for循环语句语法中,for关键字后面会有一个“变量名”,变量名依次获取in关键字后面的变量取值列表内容(以空格分隔),每次仅取一个;
然后进入循环(do和done之间的部分)执行循环内的所有指令,当执行到done时结束本次循环;
之后,“变量名”再继续获取变量列表里的下一个变量值,继续执行循环内的所有指令,当执行到done时结束返回;
以此类推,直到取完变量列表里的最后一个值并进入循环执行到done结束为止。


第二种for循环语句称为C语言型for循环语句,其语法结构如下:

for ((exp1;exp2;exp3))
do
	指令...
done

for关键字后的双括号内是三个表达式,第一个是变量初始化(例如:i=0),
第二个为变量的范围(例如:i<100),第三个为变量自增或自减(例如:i++)。
当第一个表达式的初始化值符合第二个变量的范围时,就进入循环执行;
当条件不满足时就退出循环。


[root@zabbix ~]# cat for_1.sh 
for ((i=1;i<=3;i++))
do
    echo $i
done 

范例11-1:for和while循环的对比

[root@zabbix 0511]# cat while_1.sh 
i=1
while ((i<=3))
do
    echo $i
   ((i++))
done

特别说明:

1)如果希望程序持续运行,则多用while,包括守护进程。

2)如果是有限次循环,则多用for,实际工作中使用for的机会更多。

11.2 for循环语句的基础实践

11.2.1 竖向打印数字

范例11-2:竖向打印5、4、3、2、1这5个数字。

参考答案1:直接列出元素的方法。

[root@zabbix 0511]# cat for_num.sh 
for num in 5 4 3 2 1
do
    echo $num
done

参考答案2:利用大括号{}生成数字序列的方法。

[root@zabbix 0511]# echo {5..1}
5 4 3 2 1
[root@zabbix 0511]# cat for_num.sh 
for num in {5..1}
do
    echo $num
done

参考答案3:采用seq生成数字序列的用法(这里先简略介绍,后文有细讲)。

for num in {5..1}
do
    echo $num
done

11.2.2 打印输出当前目录下文件名

范例11-3:获取当前目录下的目录或文件名,并将其作为变量列表打印输出。

模拟数据如下:

[root@zabbix 0511]# mkdir -p /test/{test.txt,oldboy.txt,oldgirl.rxt}
[root@zabbix 0511]# ll /test/
total 0
drwxr-xr-x 2 root root 6 May 11 14:52 oldboy.txt
drwxr-xr-x 2 root root 6 May 11 14:52 oldgirl.rxt
drwxr-xr-x 2 root root 6 May 11 14:52 test.txt
[root@zabbix 0511]#

实现代码如下:

[root@zabbix 0511]# cat for_file.sh 
cd /test
for filename in `ls`
do
    echo $filename
done

11.2.3 批量修改文件扩展名

范例11-4:用for循环批量修改文件扩展名(把txt改成jpg)。

[root@zabbix 0511]# touch /test/{oldboy.txt,oldgirl.txt,test.txt}
[root@zabbix 0511]# ls /test/
oldboy.txt  oldgirl.txt  test.txt
[root@zabbix 0511]# cat for_ext.sh
#!/bin/bash
cd /test
for filename in `ls|grep "txt$"`
do
    mv $filename `echo $filename|cut -d . -f1`.gif
done
[root@zabbix 0511]# sh for_ext.sh 
[root@zabbix 0511]# ls /test/
oldboy.gif  oldgirl.gif  test.gif

实际上,本题还有更简单的实现方法,即通过rename命令来直接实现,如下:

[root@zabbix test]# ls
oldboy.gif  oldgirl.gif  test.gif
[root@zabbix test]# rename "gif" "txt" *.gif
[root@zabbix test]# ls
oldboy.txt  oldgirl.txt  test.txt

11.3 for循环语句的企业案例

11.3.1 在Linux下批量修改文件名

范例11-5:在Linux下批量修改文件名,将文件名中包含的“_finished”去掉。

提示:通过此题的解答可以学习到sed、awk、rename、mv等命令的实战应用。

本题的基本解题思路和范例11-4类似,先进行单个文件的改名,然后再用循环实现批量改名,这也是最常规的做法,
当然,还可以用专业的改名工具rename来处理(本节主要是学习for循环知识)。

参考代码如下:

[root@zabbix test]# cat for_file.sh 
#!/bin/bash
cd /test
touch stu_10246_{1..5}_finished.jpg
ls *finished*
for filename in `ls *finished*`
do
    mv $filename `echo $filename |sed 's/_finished//g'`
done

其余方法实现:

  1. ls + awk + bash 实现
ls |awk -F "." '{print "mv " $0,$1"_finished."$2}'|bash
  1. 专业命令rename实现
rename "_finished" "" *jpg

11.3.2 打印九九乘法表

范例11-8:打印九九乘法表,实现图形如图11-3所示。

参考代码:

[root@zabbix 0511]# cat for_nn.sh 
#!/bin/bash
## 添加背景色:白底黑字
COLOR='\e[47;30m'
RES='\e[0m'
for ((i=1;i<=9;i++))
do
    for ((j=1;j<=i;j++))
    do
	if [ `echo $((${j}*${i}))` -le 9 ];then
	  echo -en "${COLOR}${j}x${i}=$((${j}*${i})) ${RES}\t"  ## 格式控制
	else
	  echo -en "${COLOR}${j}x${i}=$((${j}*${i}))${RES}\t"	## 格式控制
	fi
    done
    echo
done

11.3.3 计算从1加到100之和(用C的for)

  1. for循环实现:
[root@zabbix 0511]# cat for_oneto100.sh 
sum=0
for ((i=1;i<=100;i++))
do
    ((sum=sum+i))
done
echo $sum
  1. while循环实现:
[root@zabbix 0511]# cat while_oneto100.sh 
i=1
sum=0
while ((i<=100))
do
    ((sum=sum+i))
    ((i++))
done
echo $sum
  1. 公式法实现:n*(n+1)/2
[root@zabbix 0511]# echo $((100*(1+100)/2))
5050

11.4 for循环语句的企业高级实战案例

11.4.1实现MySQL分库备份的脚本

范例11-11:实现MySQL分库备份的脚本。

第一步:批量创建数据库

​ 基本的批量建库脚本如下,这里使用for循环在数据库服务器里批量创建数据库。

[root@zabbix 0511]# cat for_createDBs.sh
#!/bin/bash
Path_mysql="/application/mysql/bin:$PATH"
MYUSER=root
MYPASS=oldboy123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
for dbname in oldboy oldgirl moox shiban web
do
	$MYCMD -e "create database $dbname"
done
## 说明:不登录数据库创建数据库的命令为
## mysql -uroot -poldboy123 -S /data/3306/mysql.sock -e"create database oldboy; "

第二步:分库备份

​ 分库备份数据库(即每个库一个文件)的命令如下:

[root@zabbix 0511]# cat for_dumpDBs.sh
#!/bin/bash
Path_mysql="/application/mysql/bin:$PATH"
PATH_BACKDB=/server/backup
MYUSER=root
MYPASS=oldboy123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
[ -d $PATH_BACKDB ] || mkdir -p $PATH_BACKDB
for dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`
do
	$MYDUMP $dbname|gzip >$PATH_BACKDB/${dnbame}_$(date +%F-%T).tar.gz
done
## 说明:备份数据库的命令为
mysqldump -uroot -poldboy123 -S /data/3306/mysql.sock oldboy |gzip>/server/backup/oldboy_$(date +%F).sql.gz。

11.4.2 实现MySQL分库分表备份的脚本

范例11-12:实现MySQL分库分表备份的脚本。

第一步:准备测试数据:通过写脚本批量建表并插入数据

[root@zabbix 0511]# cat for_createTBs.sh
#!/bin/bash
Path_mysql="/application/mysql/bin:$PATH"
MYUSER=root
MYPASS=oldboy123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
for dbname in oldboy oldgirl moox shiban web
do
	$MYCMD -e "use $dbname;create teble test(id int,name varchar(16));insert into test values(1,'testdata');"
done

第二步:使用脚本查看测试数据结果:

[root@zabbix 0511]# cat for_selectTBs.sh
#!/bin/bash
Path_mysql="/application/mysql/bin:$PATH"
MYUSER=root
MYPASS=oldboy123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
for dbname in oldboy oldgirl moox shiban web
do
	echo "======== ${dbname}.test ============" 
	$MYCMD -e "use $dbname;select * from ${dbname}.test;"
done

第三步:最终形成脚本

[root@zabbix 0511]# cat for_dumpDBs_TBs.sh
#!/bin/bash
Path_mysql="/application/mysql/bin:$PATH"
PATH_BACKDB=/server/backup
MYUSER=root
MYPASS=oldboy123
SOCKET=/data/3306/mysql.sock
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
[ -d $PATH_BACKDB ] || mkdir -p $PATH_BACKDB
for dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`
do
	PATH_table=`mkdir -p $PATH_BACKDB/${dbname}_$(date +%F)`
	for table in `$MYCMD -e "show tables from $dbname;"|sed '1d'`
	do
		$MYDUMP $dbname $table |gzip > $PATH_table/${dbname}_${table}.sql.gz
	done
done

11.4.3 批量检查Web服务并邮件报警

例11-13:在生产环境下批量检查Web服务是否正常,并且发送相关邮件或手机报警信息。

[root@zabbix 0512]# cat for_web.sh 
#!/bin/bash
MYPATH=/server/scripts
MAIL_GROUP="2144865225@qq.com 3321322512@qq.com"
PAGER_GROUP="10086 10010"
LOG_FILE="/tmp/web_check.log"

[ -d $MYPATH ] || mkdir -p $MYPATH
function UrlList(){
    cat >$MYPATH/domain.list<<-zfd
    http://blog.moox.com
    http://bbs.moox.com
    http://www.moox.com
    http://www.baidu.com
    http://172.16.1.71
zfd
}
function CheckUrl(){
    FAILCOUNT=0
    for ((i=1;i<=3;i++))
    do
	wget -T 5 --tries=1 --spider $1 &>/dev/null
	if [ $? -ne 0 ];then
	    let FAILCOUNT+=1
	else
	    break
	fi
    done
    return $FAILCOUNT
}
function MyMail(){
    local SUBJECT_CONTENT=$1
    for MAIL_USER in `echo $MAIL_GROUP`
    do
	mail -s "$SUBJECT_CONTENT" $MAIL_USER < $LOG_FILE
    done
}
function MyPager(){
    for PAGER_USER in `echo $PAGER_GROUP`
    do
	TITLE=$1
	CONTACT=$PAGER_USER
	HTTPGW=http://oldboy.sms.cn/smsproxy/sendsms.action
	curl -d cdkey=5ADF-EFA -d password=OLDBOY -d phone=$CONTACT -d message="$TITLE[$2]" $HTTPGW &>/dev/null
    done
}
function SendMsg(){
    ERRORS=$1
    echo "error count: $ERRORS "
    if [ $1 -ge 3 ];then
	RETVAL=1
	NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`
	SUBJECT_CONTENT="http://$2 is error, ${NOW_TIME}"
	echo -e "$SUBJECT_CONTENT"|tee $LOG_FILE 
	MyMail $SUBJECT_CONTENT 2>/dev/null
	MyPager $SUBJECT_CONTENT $NOW_TIME 2>/dev/null
    else
	echo "http://$2 is ok."
	echo "action:check err count:$1"
	RETVAL=0
    fi
    return $RETVAL
}
function main(){
    UrlList
    for url in `cat $MYPATH/domain.list`
    do
	echo "checking $url ..."
	CheckUrl $url 
	SendMsg $? $url
    done
}
main
[root@zabbix 0512]# sh for_web.sh

11.4.4 批量创建系统账号并设置密码

范例11-14:批量创建10个系统账号(oldboy01-oldboy10),并设置密码(密码为随机数,要求是字符和数字的混合)。

参考答案1:passwd无交互设置密码方式

1)创建10个系统账号,即oldboy01~oldboy10。

[root@zabbix 0512]# seq -s " " -w 10
01 02 03 04 05 06 07 08 09 10
[root@zabbix 0512]# echo {01..10}
01 02 03 04 05 06 07 08 09 10

2)要想通过脚本创建账号,必须知道如何实现无交互设置密码

[root@zabbix 0512]# useradd oldgirl
[root@zabbix 0512]# echo 123456|passwd --stdin oldgirl 
Changing password for user oldgirl.
passwd: all authentication tokens updated successfully.

3)密码为随机数,并且是8位字符串

RANDOM+md5sum方法

[root@zabbix 0512]# echo $RANDOM|md5sum |cut -c 5-12
f1139af0

4)形成脚本,调用系统函数库让输出更美观,同时增强逻辑性

[root@zabbix 0512]# cat for_useradd.sh 
#!/bin/bash
. /etc/init.d/functions
user="oldboy"
passfile="/tmp/user.log"
for num in `seq -w 11 15`
do
    useradd ${user}${num} &>/dev/null
    ##  提示:注意随机数的字符串要定义成变量,否则,每次执行结果都会不相同。
    pass="`echo $RANDOM |md5sum| cut -c 3-11`"
    echo "$pass"|passwd --stdin $user$num &>/dev/null
    echo -e "user: $user$num\t passwd: $pass" >>$passfile
    if [ $? -eq 0 ];then
	action $"$user$num is OK" /bin/true
    else
	action $"$user$num is failed" /bin/false
    fi
done
echo -----------------
cat $passfile && >$passfile
[root@zabbix 0512]# sh for_useradd.sh

参考答案2:chpasswd命令方式设置密码

1)按照参考答案1的思路正常创建账号。

2)要批量创建密码,可使用chpasswd来实现,chpasswd是一个批量更新用户口令的工具。

chpasswd命令介绍:

## 1. 单个创建用户并设置密码
useradd oldgirl01
echo "oldgirl01:123456"|chpasswd
## 2. 给多个用户修改密码
[root@zabbix 0512]# for user in oldboy1{1..4};do userdel $user;done
## 说明:用户必须存在。
[root@zabbix 0512]# for user in oldboy1{1..4};do useradd $user&>/dev/null;done
[root@zabbix 0512]# cat /tmp/user.log  ## 用户名和密码之间不能有空格
oldboy11:acd38594e
oldboy12:8598c6699
oldboy13:5b0f8388b
oldboy14:863255424
[root@zabbix 0512]# chpasswd </tmp/user.log 
[root@zabbix 0512]# 

shell实现脚本:

[root@zabbix 0512]# > /tmp/user.log 
[root@zabbix 0512]# cat for_useradd.sh 
#!/bin/bash
. /etc/init.d/functions
user="oldboy"
passfile="/tmp/user.log"
for num in `seq -w 11 15`
do
    useradd ${user}${num} &>/dev/null
    pass="`echo $RANDOM |md5sum| cut -c 3-11`"
    #echo "$pass"|passwd --stdin $user$num &>/dev/null
    echo -e "${user}${num}:$pass" >>$passfile
    if [ $? -eq 0 ];then
	action $"$user$num is OK" /bin/true
    else
	action $"$user$num is failed" /bin/false
    fi
done
echo -----------------
chpasswd < $passfile
cat $passfile && >$passfile

11.5 Linux系统产生随机数的6中方法

方法1:通过系统环境变量($RANDOM)实现,示例代码如下


RANDOM的随机数范围为0~32767,因此,加密性不是很好,可以通过在输出的随机数后增加加密字符串
》(就是和密码生成有关的一个字符串)的方式解决,最后再一起执行md5sum操作并截取结果的后n位,
这样一来,就无法根据随机数范围0~32767来猜出具体结果了。


[root@zabbix 0512]# echo $RANDOM
1320
[root@zabbix 0512]# echo $RANDOM
14048
[root@zabbix 0512]# echo $RANDOM|md5sum |cut -c 1-10
a7bc8e8617

方法2:通过openssl产生随机数,示例代码如下。


令数字与大小写字符相结合,并且带上特殊字符,可以达到很长的位数,这样的随机数很安全。


[root@zabbix 0512]# openssl rand -base64 60
dtOjbwutVaZ6Wk7nCo/KOxqK7zWaYsaY582DW0FoMr2gYwGWhD02Hq1A4fGXJhtFVdE7D/9MUv3qAM8G

方法3:通过时间(date)获得随机数,示例代码如下。

[root@zabbix 0512]# date +%s%N
1589265384941362238
[root@zabbix 0512]# date +%s%N
1589265392066253068

方法4:通过/dev/urandom配合chksum生成随机数。


/dev/random设备存储着系统当前运行环境的实时数据。它可以看作系统在某个时候的唯一值,
因此可以用作随机数元数据。我们可以通过文件读取的方式,读到里面的数据。
/dev/urandom这个设备的数据与random里的一样。只是,它是非阻塞的随机数发生器,读取操作不会产生阻塞。


[root@zabbix 0512]# head /dev/urandom |cksum
1773856086 2639
[root@zabbix 0512]# head /dev/urandom |cksum
2770058246 1782

方法5:通过UUID生成随机数。


UUID码全称是通用唯一识别码(Universally Unique Identifier, UUID),它是一个软件建构的标准,
亦为自由软件基金会(Open Software Foundation, OSF)的组织在分布式计算环境(Distributed ComputingEnvironment, DCE)领域的一部分。

UUID的目的是让分布式系统中的所有元素都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。
如此一来,每个人都可以创建不与其他人发生冲突的UUID。在这样的情况下,就不需要考虑数据库创建时的名称重复问题了。
它会让网络中任何一台计算机所生成的UUID码都是互联网整个服务器网络中唯一的编码。
它的原信息会加入硬件、时间、机器当前运行信息等。


[root@zabbix ~]# cat /proc/sys/kernel/random/uuid 
49b37c77-6fe8-4854-9e43-6f76869fc0f7
[root@zabbix ~]# cat /proc/sys/kernel/random/uuid 
46ac7362-7754-451f-818b-20317e5ca3c8

方法6:使用expect附带的mkpasswd生成随机数

mkpasswd命令依赖于数据包expect,因此必须通过“yum install expect -y”命令先安装该数据包:

[root@zabbix ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1
r1*X9BZyp
[root@zabbix ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1
fH.96MKhl
-- 参数:
The -l 	: the length of the password. 		default is 9
The -d 	: the number of digits, 			default is 2.
The -c 	: the number of lowercase. 			default is 2
The -C	: the number of uppercase,			default is 2
The -s	: the number of special characters .default is 1.
-- 上面的随机数长短不一,如何统一格式化呢?解答:使用md5sum命令。
[root@zabbix ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1|md5sum |cut -c 3-11
535020bca

11.6 select循环语句介绍及语法


select循环语句的主要作用可能就是创建菜单,在执行带select循环语句的脚本时,
输出会按照数字顺序的列表显示一个菜单项,并显示提示符(默认是#? ),
同时等待用户输入数字进行选择,下面就来带大家看看生成菜单项的语法及具体案例实践。


第一种: for循环语句为变量取值型,语法结构如下:

select 变量名 [ in 菜单取值列表]
do
	指令...
done

提示:bash帮助语法显示:select name [ in word ]; do list; done

在此结构中“in变量取值列表”可省略,省略时相当于使用in“\(@”,使用for i就相当于使用for i in“\)@”。

与for循环不同点:

select循环执行后会出现菜单项等待用户选择(不会自动循环所有变量列表),而用户输入的只能是菜单项前面的数字序号,
每输入一次对应的序号就会执行一次循环,直到变量后面对应列表取完为止。

select循环结构执行流程对应的逻辑图如图11-5所示。

11.7 selec循环语句案例

11.7.1 用select循环打印简单菜单项的多种实现方法

1 select直接使用列表字符串

[root@zabbix 0513]# cat select_1.sh 
#!/bin/bash
select name in oldboy oldgirl moox
do
    echo $name
done
# 执行脚本后打印带数字序列(数字加右小括号)的菜单项,内容就是变量列表的内容
[root@zabbix 0513]# sh select_1.sh 
1) oldboy
2) oldgirl
3) moox
#? 1		--- 必须输入序列号,输入错误则返回空,界面不是很优雅
oldboy
#? 2
oldgirl
#? 3
moox
#? 4

2 select采用数组做变量列表

[root@zabbix 0513]# cat select_arr.sh 
#!/bin/bash
array=(oldboy oldgirl moox)
select name in "${array[@]}"
do
    echo $name
done
[root@zabbix 0513]# sh select_arr.sh
执行结果与上例一样

3 select把命令结果作为变量列表(菜单项)

(1)数据准备

[root@zabbix 0513]# mkdir /tmp/test
[root@zabbix 0513]# mkdir /tmp/test/{oldboy,oldgirl,moox}

(2)脚本开发

[root@zabbix 0513]# cat select_ls.sh 
#!/bin/bash
select name in  `ls /tmp/test`
do
    echo $name
done

11.7.2 select打印菜单:提示符功能+web服务菜单实践


通过上一个范例我们了解到,select循环菜单项的默认提示很不友好,
并且输入的是数字,打印的变量值却是数字对应的菜单项内容。
那能不能针对默认提示符以及打印输入内容进行调整呢?当然可以,且看下面的案例。


范例11-16:调整select循环菜单项的默认提示符及利用select变量打印数字序号。

[root@zabbix 0513]# cat select_menu.sh 
#!/bin/bash
PS3="please select a num from menu:"
select name in oldboy oldgirl moox
do
   echo -e "I guess you selected the num is:\n $REPLY) $name"
done
[root@zabbix 0513]# sh select_menu.sh 
1) oldboy
2) oldgirl
3) moox
please select a num from menu:4
I guess you selected the num is:
 4)  								# == "$REPLY)"
please select a num from menu:  	# == "PS3"

本范例重点讲解了select循环的两个特殊变量,
其中PS3系统环境变量用于控制select循环的提示符,
REPLY变量用于获取菜单项对应的数字,也就是用户输入的数字。

范例11-17:打印选择菜单,按照选择一键安装不同的Web服务。

示例菜单:

[root@zabbix 0513]# sh select_WebMenu.sh 
	1.[install lamp]
	2.[install lnmp]
	3.[exit]
	Please input the num you choose:

要求:
1)当用户输入1时,输出“start installing lamp.”提示,然后执行/server/scripts/lamp.sh,
输出"lamp isinstalled"后退出脚本,这就是实际工作中所用的lamp一键安装脚本;

2)当用户输入2时,输出“start installing lnmp.”提示,然后执行/server/scripts/lnmp.sh,
输出"lnmp isinstalled"后退出脚本,这就是实际工作中所用的lnmp一键安装脚本;

3)当输入3时,退出当前菜单及脚本;
4)当输入任何其他字符时,给出提示“Input error”后退出脚本;
5)要对执行的脚本进行相关的条件判断,
例如:脚本文件是否存在,是否可执行等判断,尽量用上前面讲解的知识点。

解答:本范例和范例6-36是一道题,但是采用的实现方法却完全不同,
本例将采用select循环结构实现范例6-36脚本的升级版

[root@zabbix 0513]# cat select_webInstall.sh 
#!/bin/bash
RETVAL=0
path=/server/scripts
[ ! -d "$path" ] && mkdir -p $path
function Usage(){
    echo "USGE: $0 argv"
    return 1
}
function InstallService(){
    [ $# -ne 1 ] &&{
		Usage
    }
    local RETVAL=0
    service=$1
    echo "start install $service ..."
    sleep 2
    if [ -x "$path/${service}.sh" ];then
		$path/${service}.sh
		return $RETVAL
    else
		echo "$path/${service}.sh not exist or can not be exec."
	return 1
    fi
}
function main(){
    PS3="Please input the num you choose: "
    select var in "Install lamp" "Install lnmp" "exit"
    do
		case $var in
	    	"Install lamp")
				InstallService lamp
				RETVAL=$?
				;;
	    	"Install lnmp")
				InstallService lnmp
				RETVAL=$?
				;;
	    	"exit")
				echo bye.
				return 3
				;;
	    	*)
				echo "the num you input must be {1|2|3}"
				echo "Input Error."
		esac
    done
    exit $RETVAL
}
main
########################################################
[root@zabbix 0513]# sh select_webInstall.sh 
1) Install lamp
2) Install lnmp
3) exit
Please input the num you choose: 1
start install lamp ...
lamp is installed
Please input the num you choose: 2
start install lnmp ...
/server/scripts/lnmp.sh not exist or can not be exec.
Please input the num you choose: 4
the num you input must be {1|2|3}
Input Error.
Please input the num you choose: 3
bye.
[root@zabbix 0513]#

将上述脚本中case部分使用系统变量REPLY实现改写:

case $REPLY in
	"1")
		InstallService lamp
		RETVAL=$?
		;;
	"2")
		InstallService lnmp
		RETVAL=$?
		;;
	"3")
		echo bye.
		return 3
		;;
	*)
		echo "the num you input must be {1|2|3}"
		echo "Input Error."
esac

posted on 2020-05-13 14:22  zhangfd  阅读(576)  评论(0编辑  收藏  举报