shell脚本编程(循环结构)

目录

一.shell循环-for语句

1.1for循环语法

1.2并发执行

二.shell循环-while语句

2.1while循环语法

三.shell循环-until语句

3.1until循环语法

四.shift命令

4.1shift参数详解

五.其他参数

5.1continue、break、exit命令


一.shell循环-for语句

1.1for循环语法

for i in {取值范围}    # for 关键字  i 变量名 in 关键字  取值范围格式 1 2 3 4 5
do                    # do 循环体的开始
				    循环体
done                  # done 循环体的结束	

例如,循环输出1-100:

#!/usr/bin/env bash
#
# Author:
# Date: 2019/**/**
for i in {1..100} 
do
				echo $i 
done

1.2并发执行

shell脚本的执行效率虽高,但当任务量巨大时仍然需要较长的时间,尤其是需要执行一大批的命令时。因为默认情况下,shell脚本中的命令是串行执行的。如果这些命令相互之间是独立的,则可以使用“并发”的方式执行这些命令,这样可以更好地利用系统资源,提升运行效率,缩短脚本执行的时间。如果命令相互之间存在交互,则情况就复杂了,那么不建议使用shell脚本来完成多线程的实现。

1.模拟场景

我们已知shell脚本中的命令是串行执行的,他会一个个依次执行循环中的内容,如果一个循环之中的事务处理时间较长,例如下面事务处理一个需要1秒,循环10次需要10秒,如果是更为庞大的数据,则会严重拖慢时间,降低效率。

#!/bin/bash

all_num=10  #定义一个变量为10

for num in `seq 1 ${all_num}` #依次循环,一共10次
do
	sleep 1     #睡眠一秒,模拟事务执行的时间
	echo ${num}  #输出结果
done

 一次一秒,依次输出结果:

1
2
3
4
5
6
7
8
9
10

由此,我们需要一个解决方法,来提高shell脚本在循环事务中的效率,以下为总结的一些方法供参考:

方案一:使用"&"使命令后台运行

在linux中,在命令的末尾加上&符号,则表示该命令将在后台执行,这样后面的命令不用等待前面的命令执行完就可以开始执行了。循环体内可能有多条命令,则可以以{}括起来,在大括号后面添加&符号。例如:

#测试生产环境中ip地址的可用性

#!/usr/bin/env bash 
# Author:       #{}&  并发
>ip_alive.txt     # 存放可用ip的文件
>ip_down.txt      # 存放不可用ip的文件
a=$(date +%H%M%S)  #定义一个记录时间的变量a
segment="192.168.161" 
for i in {2..254}
do
        {
        ping -c1 $segment.$i &>/dev/null   # 依次pingIP
        if [ $? -eq 0 ];then
        				printf "alive: $segment.$i\n" >>ip_alive.txt  #ping通则存放至文件夹
        else
        				printf "down: $segment.$i\n" >>ip_down.txt #未ping通存放至另一文件
        fi
        }&  #将上述内容并发执行
done

b=$(date +%H%M%S)  #定义一个记录时间的变量a

echo -e "startTime:\t$a"  #输出时间a
echo -e "endTime:\t$b"  # 输出时间b
echo "finish..."

通过结果可知,没有一个个打印ip,而是直接先输出了时间a,b。而后一次性输出了所有ip结果,这是因为循环体内的命令全部进入后台,所以均在输出时间a,b运行完毕以后输出ip。这是由于循环体在后台执行,没有占用脚本主进程的时间。那么我们这里设置的a,b就没有实际意义了,这时候我们就要想办法,先让循环体运行结束,再执行循环体外的命令。

由此我们可以参考如下:

方案二:命令后台运行+wait命令

解决上面的问题,只需要在上述循环体的done语句后面加上wait命令,该命令等待当前脚本进程下的子进程结束,再运行后面的语句。

#!/usr/bin/env bash 
# Author:       #{}&  并发
>ip_alive.txt     # 存放可用ip的文件
>ip_down.txt      # 存放不可用ip的文件
a=$(date +%H%M%S)  #定义一个记录时间的变量a
segment="192.168.161" 
for i in {2..254}
do
        {
        ping -c1 $segment.$i &>/dev/null   # 依次pingIP
        if [ $? -eq 0 ];then
        				printf "alive: $segment.$i\n" >>ip_alive.txt  #ping通则存放至文件夹
        else
        				printf "down: $segment.$i\n" >>ip_down.txt #未ping通存放至另一文件
        fi
        }&  #将上述内容并发执行
done
wait #等待前面命令执行完毕,再执行后面命令
b=$(date +%H%M%S)  #定义一个记录时间的变量a

echo -e "startTime:\t$a"  #输出时间a
echo -e "endTime:\t$b"  # 输出时间b
echo "finish..."

但这样依然存在一个问题:
因为&使得所有循环体内的命令全部进入后台运行,那么倘若循环的次数很多,会使操作系统在瞬间创建出所有的子进程,这会非常消耗系统的资源。如果循环体内的命令又很消耗系统资源,则结果可想而知。

最好的方法是并发的进程是可配置的。

方案三:使用xargs -P控制并发数

xargs命令有一个-P参数,表示支持的最大进程数,默认为1。为0时表示尽可能地大,即方案2的效果。

#/bin/bash

all_num=10
thread_num=5

a=$(date +%H%M%S)

seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c "sleep 1;echo {}"

b=$(date +%H%M%S)

echo -e "startTime:\t$a"
echo -e "endTime:\t$b"

方案四:使用GNU parallel命令控制并发数

GNU parallel命令是非常强大的并行计算命令,使用-j参数控制其并发数量。

#/bin/bash

all_num=10
thread_num=6

a=$(date +%H%M%S)


parallel -j 5 "sleep 1;echo {}" ::: `seq 1 10`

b=$(date +%H%M%S)

echo -e "startTime:\t$a"
echo -e "endTime:\t$b"

二.shell循环-while语句

2.1while循环语法

while 条件    # while 关键字  条件  [ $1 -lt 10 ] ,while循环,条件为真的情况下,会循环
do
		循环体
done

 举例:创建一个脚本,查看是否存在该用户,若无则创建该用户

#!/bin/bash
while read user
do
		id $user &>/dev/null 
		if [ $? -eq 0 ];then
				echo "$user is already exists"
		else
				useradd $user
				echo "create $user successfully"
		fi
done < user.txt

三.shell循环-until语句

3.1until循环语法

until 条件 # 当后面的条件表达式,为假的时候进行循环,当他为真了就停止循环了。
do
循环体
done

四.shift命令

4.1shift参数详解

位置参数可以用shift命令从左往右移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢 弃,$0不移动。不带参数的shift命令相当于shift 1。
对于位置变量或命令行参数,其个数必须是确定的,或者当 Shell 程序不知道其个数时,可以把所有参数一起赋值给变量 $*。
若用户要求 Shell 在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在 $1 后为 $2,在 $2 后面为 $3 等,则需要用shift把所有参数变成$1

举例:

#测试 shift 命令(x_shift3.sh)
[root@newrain shell]# cat x_shift3.sh 
#!/bin/bash
shift   #位置参数从左往右移动一位
echo "第一个位置参数: $1"
[root@newrain shell]# bash x_shift3.sh 2 3
第一个位置参数: 3

五.其他参数

5.1continue、break、exit命令


1.break
结束并退出本次循环

2.continue 
在循环中不执行continue下面的代码,转而进入下一轮循环

3.exit
退出脚本,常带一个整数给系统,如 exit 0

可理解为:break是立马跳出循环;continue是跳出当前条件循环,继续下一轮条件循环;exit是直接退出整个脚本 
例如: 
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。 break命令允许跳出所有循环(终止执行后面的所有循环)。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨影萧萧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值