shell循环

shell循环

循环的分类

循环名称 循环的含义 使用场景
while循环 当型循环 死循环/有条件的循环/一行一行的读取的文件
do until 直到型循环 没啥用.
for 循环 通用型 很多场景都可以使用

循环语法

# while 循环
while <条件表达式>;do
	cmd1
	cmd2
	cmd3
done

while <条件表达式>
do
	cmd1
	cmd2
	cmd3
done

# 死循环
while true;do
	echo 'hei hei hei'
done

while [ 1 -eq 1 ];do
	echo 'hei hei hei'
done

while :;do
	echo 'hei hei hei'
done

使用while循环模拟for循环seq

n=1
while [ $n -le 10 ];do
        echo $n
        ((n++))
done

for n in `seq 10`;do
	echo $n
done

使用while循环实现1+100

n=1
num=0
while [ $n -le 100 ];do
        ((num=num+n))
        ((n++))
done
echo $num

# 其他方法
[root@m01 ~]# echo {1..100}|tr ' ' '+'|bc

[root@m01 ~]# seq -s + 100|bc

[root@m01 ~]# seq 100|awk '{m=m+$1}END{print m}'

[root@m01 ~]# awk 'BEGIN{for(i=1;i<=100;i++)sum=sum+i;print sum}'

for循环

语法一

无法指定循环次数,变量表达式中有多少内容就循环多少次

for i in 1 2 3 4;do
        echo $i
done

for i in 变量表达式
do
	cmd1
	cmd2
done

变量表达式:
	- 可以是文件中的内容(按空格循环)
	- 可以是序列命令的内容
	- 可以是数组中的内容
	- 可以是以空格为分隔符的字符串
	
# 文件内容
for i in `cat 1.txt`;do
	echo $i
done

for i in ${cat 1.txt};do
	echo $i
done

# 序列内容
for i in `seq 10`;do
	echo $i
done

# 数组
array=(cjk dsb wls)
for i in ${array[*]};do
	echo$i
done

# 以空格为分隔符
name="cjk dsb wls"
for i in $name;do
	echo $i
done

语法二

指定循环的次数

for ((i=1;i<=10;i++));do
	echo $i
done

死循环

for (( ; ; ));do
	echo 123
done

循环的控制语句

Break

# break(跳出循环)
break命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。
n=0
while [ $n -lt 10 ];do
        ((n++))
        if [ $n -eq 5 ];then
                break
fi
        echo $n
done

Continue

# continue(跳出循环)
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

n=0
while [ $n -lt 10 ];do
        ((n++))
        if [ $n -eq 5 ];then
                continue
fi
        echo $n
done

for循环读取文件

# for 循环读取文件
for txt in `cat 1.txt`;do
        echo $txt
done

while循环读取文件

# while 读取文件
1.
exec < 1.txt
while read line;do
        echo '-------'
        echo $line
done

2.
while read line;do
        echo '-------'
        echo $line
done <1.txt

3.
cat 1.txt|while read line;do
        echo '-------'
        echo $line
done

while练习

写一个脚本,读取下面文件内容,并算出所有人年龄总和
[root@zabbix01 ~]# cat student.txt
曾老湿 18
苍井空 20
武藤兰 33
天海翼 32
西野翔 18

# 方法一
sum=0
while read line;do
        age=`echo $line|awk '{print $2}'`
        ((sum+=age))
done < age.txt
echo $sum

# 方法二
exec < age.txt
sum=0
while read line;do
        age=`echo $line|awk '{print $2}'`
        ((sum+=age))
done 
echo $sum

案例一

日志分析案例
写一个shell脚本,防止DDOS攻击,先分析日志,监控某一个IP并发连接数,若短时内PV达到100阈值,则调用防火墙命令,封掉该IP。
可以分析nginx日志或者查看当前网络连接数 ss -ant 或者 netstat -ant
这里使用一个生产的日志 netstat.log


# 作业
grep -w 'tcp' /root/netstat.log|awk '{print $5}'|sort|uniq -c|sort -r|while read line;do
        test=`echo ${line}|awk '{print $1}'`
        ip=`echo ${line}|awk '{print $2}'|awk -F : '{print $1}'`
        if [ $test -gt 100 ];then
        firewall-cmd --add-source=${ip} --zone=drop
fi
done

案例二

在指定目录下,通过随机10个小写字母,然后生成一个文件名为: 随机字母_zls.txt 的文件

# 生成随机内容的方法
## 方法一:
[root@zabbix01 ~]# openssl rand -base64 10
UUBtKUvUkEfcEw==
## 方法二:
[root@zabbix01 ~]# echo $((RANDOM))|md5sum
## 方法三:
[root@zabbix01 ~]# date +%N|md5sum
3fd3a5c57def5f89481e1961fceb13e8
## 方法四:
tr -cd 'a-zA-Z0-9'</dev/urandom|head -c 10

# 作业
 random=`tr -cd 'a-z'</dev/urandom|head -c 10`
mkdir /opt/${random}_zls.txt

案例三

# 提示一:变量子串方法
# 提示二:sed awk方法
# 提示三:命令拼接
# 提示四:rename

rename zls.txt cls.TXT /root/*.txt
#!/bin/bash
for name in `ls -1 /abc`;do
	#mv /abc/${name%.*}.yml /abc/${name%.*}.j2
	mv /abc/$name /abc/${name//j2/yml}
done

案例四

创建100个系统用户,生成随机密码
并将用户名和密码保存到文件中
用户名:密码

# 作业
for i in `seq 100`;do
        useradd user$i
        pass=`sh ./l.sh`
        echo "user$i:$pass" >> /tmp/password
        echo "----------" >> /tmp/password
        echo ${pass}|passwd --stdin user$i
done

案例五

现在我们要模拟黑客,来扫描,指定网段内存活的主机

# 作业
[root@m01 ~]# cat dk.sh
#!/bin/bash

# File Name: __dk.sh__
# Version: __v1.1__ 
# Author: __Driverwang__ 
# Mail: __2794552827@qq.com__ 
# Blog: __https://blog.driverzeng.com__ 
# DateTime: __2022-07-25 17:45__

. /etc/init.d/functions
#for n in `seq 254`;do
# ping -c 1 10.0.0.$n
#done
for n in `seq 254`;do
{
	ping -c1 -W1 -i1 10.0.0.$n &>/dev/null
	if [ $? -eq 0 ];then
	  action 10.0.0.$n /bin/true
{	
	for port in `seq 65535`;do

	port=`echo ' '|telnet 10.0.0.${n} ${port} 2>/dev/null  |grep 'Connected'|wc -l`
	if [ $port -ne 0 ];then
		action "${port} 端口已存在" /bin/true
fi

	usleep 300
	done
} &
fi
} &
usleep 300
done

posted @ 2022-07-26 15:01  Gabydawei  阅读(137)  评论(0编辑  收藏  举报