shell循环
为什么使用循环
1.减少代码量
2.有些时候,只能用循环,不规律的情况下
3.读取文件内容
4.死循环
循环的分类
- 当型循环 while
- 直到型循环 do until
- 通用循环 for
while 循环语法
while 条件;do
chmd1
done
while 条件
do
cmd1
cmd2
done
## 死循环
while true;do
echo '123'
done
while [ 1 -eq 1 ];do
echo 456
sleep 3
done
## 开关的方式终结死循环
flag=true
num=1
while $flag;do
echo $num
if [ $num -eq 10 ];then
flag=false
fi
((num++))
done
使用while模拟seq命令
#!/bin/bash
#while true;do
# echo '123'
#done
#
#while [ 1 -eq 1 ];do
# echo 456
# sleep 3
#done
num=1
while [ $num -le $1 ];do
echo $num
((num++))
done
使用while从1加到100
num=0
count=1
while [ $count -le 100 ];do
((num+=count))
((count++))
done
echo $num
until循环(忘记)
# 语法:
until <条件表达式>;do
cmd1
done
# 例
#!/bin/bash
until false;do
echo 123
sleep 1
done
for循环
# 语法一:
for 变量名 in 变量表达式;do
cmd1
cmd2
done
## 变量表达式
1.可以是以空格为分隔符的字符串
file_name="/etc/passwd /etc/shadow /etc/gshadow /etc/group"
for file in $file_name;do
echo $file
echo '--- 分隔符 ---'
done
2.可以是以空格为分隔符的数字
for n in 1 2 3 4 5;do
echo $n
done
3.可以是一个命令的结果
for number in `ls /`;do
echo $number
done
for number in `seq 10`;do
echo $number
done
4.可以是数组
array=(zls cls wls)
for name in ${array[@]};do
echo $name
done
5.文件内容
但是要注意for并不是按行读取,如果每一行都没有空格还行,但是一旦遇到空格就...
for name in `cat student.txt`;do
echo $name
done
# 语法二:
类C语言的语法
for((i=1;i<="$1";i++));do
echo $i
done
## for的死循环
for (( ; ;));do
echo 123
sleep 1
done
循环控制语句
break跳出循环
命令允许跳出所有循环(终止执行后面的所有循环)。
num=0
for(( ; ;));do
((num++))
echo $num
sleep 1
if [ $num -eq 10 ];then
break 1
fi
done
echo "这里是循环之外..."
continue跳出循环
它不会跳出所有循环,仅仅跳出当前循环。
for n in `seq 10`;do
if [ $n -eq 5 ];then
continue 1
fi
echo $n
done
echo "这里是循环之外..."
注意:多层循环嵌套的时候,break或者continue写在哪个循环中,就只跳出一层循环(break和continue后面的数字 是指定循环层数)
#!/bin/bash
for name in `cat name.txt`;do
for age in `cat age.txt`;do
echo "$name $age"
if [ $age -eq 11 ];then
break 1
fi
done
done
for name in `cat name.txt`;do
for age in `cat age.txt`;do
echo "$name $age"
if [ $age -eq 11 ];then
break 2
fi
done
done
while读取文件内容
# 1.方法一:
cat 文件名|while read 变量名;do
cmd1
cmd2
done
例:
cat name.txt|while read line_name;do
echo $line_name
done
# 2.方法二:
while read 变量名;do
cmd1
cmd2
done < 文件名
while read line_name;do
echo $line_name
done < name.txt
# 3.方法三
exec < name.txt
while read line_name;do
echo $line_name
done
while读取文件练习
文件内容
曾老湿 18
苍井空 20
武藤兰 33
天海翼 32
西野翔 18
#!/bin/bash
count=0
while read line;do
age=${line##* }
echo $((count+=age))
done < student.txt
echo $count
日志分析案例
写一个shell脚本,防止 DDOS 攻击,先分析日志,监控某一个IP并发连接数,若短时内PV达到100阈值,则调用防火 墙命令,封掉该IP。
可以分析nginx日志或者查看当前网络连接数 ss -ant 或者 netstat -ant
# 每个IP的并发数
awk '/^tcp/{print $4}' netstat.log|sort -nr|uniq -c
# 每个IP的访问次数
ip_access=`awk '/^tcp/{print $4}' netstat.log|sort -nr|uniq -c|awk '{print $1}'`
if [ $ip_access -gt 100 ];then
firewall-cmd --add-source=$ip --zone=drop
fi
# vim ip.sh
#!/bin/bash
ip_access=`awk '/^tcp/{print $4}' netstat.log|sort -nr|uniq -c|awk -F '[ :]+' '{print $2","$3}'`
for line in $ip_access;do
count=${line%%,*}
ip=${line##*,}
if [ $count -gt 100 ];then
firewall-cmd --add-source=$ip --zone=drop
fi
done
随机文件名
# 取随机数方法
1.md5
date +%N|md5sum|cut -c 1-10
2.mkpasswd
mkpasswd -l 10
3.random
echo $RANDOM|md5sum|cut -c 1-10
4.tr
tr -cd 'a-z' </dev/urandom|head -c 10
在指定目录下,通过随机10个小写字母,然后生成10文件名为:随机字母_zls.txt的文件
随机数:tr -cd 'a-z' </dev/urandom|head -c 10
for((i=1;i<=10;i++));do
ran=`tr -cd 'a-z' </dev/urandom|head -c 10`
touch /tmp/${ran}_zls.txt
done
批量修改文件名
将/tmp/下面所有的txt文件修改为TXT
# 1.变量子串
file_path=`ls /tmp/*.txt`
for file_name in $file_path;do
mv $file_name ${file_name/txt/TXT}
done
# 2.替换
file_path=`ls /tmp/*.TXT`
for file_name in $file_path;do
new_name=`echo $file_name|tr 'TXT' 'txt'`
mv $file_name $new_name
done
# 3.rename
file_path=`ls /tmp/*.txt`
for file_name in $file_path;do
rename ${file_name%%.*}.txt ${file_name%%.*}.TXT /tmp/*.txt
done
## 创建5个用户,并且给随机密码
seq 5|awk '{print "pass=`echo $RANDOM|md5sum|cut -c 1-10`;useradd wls"$1";echo cls"$1":$pass >> /tmp/pass2.txt;echo $pass|passwd --stdin cls"$1}'|bash
快速扫描指定网段中存活的机器
. /etc/init.d/functions
for n in `seq 255`;do
{
ping -c 1 -W 0.2 -i 0.5 192.168.3.$n &>/dev/null
if [ $? -eq 0 ];then
action "192.168.3.$n" /bin/true
fi
} &
usleep 200
done
nmap -n -sn 10.0.0.0/24
figlet命令
[root@zabbix01 ~]# figlet zls
[root@zabbix01 ~]# showfigfonts
[root@zabbix01 ~]# figlet zls -f banner
[root@zabbix01 ~]# watch -n1 "date +%D%n%T|figlet -k"
作业
优化登录框
num=0
flag=true
while $flag;do
echo -e "\n-------- 登录界面 --------"
read -p "用户名: " user_name
read -p "密码: " user_pass
user_count=`awk '{print $1}' $db_file | grep -cw "$user_name"`
if [ $user_count -eq 0 ];then
while $flag;do
echo -e "\n-------- 注册界面 --------"
read -p "注册用户名: " user_name
user_count=`awk '{print $1}' $db_file | grep -cw "$user_name"`
if [ $user_count -eq 0 ];then
read -p "注册密码: " user_pass1
read -p "确认密码: " user_pass2
if [ $user_pass1 == $user_pass2 ];then
echo "$user_name 注册成功"
echo "$user_name $user_pass1" >> $db_file
break
else
echo "两次密码不一致"
((num++))
if [ $num -eq 3 ];then
flag=false
fi
fi
fi
done
else
pass=`grep -w "$user_name $user_pass" $db_file |awk '{print $2}'`
if [ "$user_pass" == "$pass" ];then
echo "登录成功"
exit 0
else
echo "密码错误请重新输入"
((num++))
if [ $num -eq 3 ];then
echo "密码输入错误三次,程序退出"
flag=false
fi
fi
fi
done