1、case语句
1.1 概述
case语句属于条件分支语句,一般用于实现有多种选择的情况,比如:菜单功能
1.2 格式
case语句格式如下:
case "变量" in
条件)
命令1
;;
条件)
命令2
;;
*)
命令3
esac
例如:
[root@m01 /server/script/devops-shell]#vim 21.case.sh
#1、vars
cat << EOF
-1 138套餐 4g流量100分钟
-2 238套餐 10g流量200分钟
其他 错误
EOF
read num
#2、判断
case "$num" in
1)
echo "138套餐"
;;
2)
echo "238套餐"
;;
*)
echo "选择错误"
esac
测试:
[root@m01 /server/script/devops-shell]#sh 21.case.sh
-1 138套餐 4g流量100分钟
-2 238套餐 10g流量200分钟
其他 错误
1
138套餐
[root@m01 /server/script/devops-shell]#sh 21.case.sh
-1 138套餐 4g流量100分钟
-2 238套餐 10g流量200分钟
其他 错误
3
选择错误
[root@m01 /server/script/devops-shell]#
案例1:判断用户输入的是yes,还是no
输入yes,y,Y,Yes,都表示yes
输入no,n,N,No,都表示no
[root@m01 /server/script/devops-shell]#vim 22.case_yes_no.sh
#1、vars
read -p "请输入yes或no:" yesno
#2、case
case "$yesno" in
yes|y|Y|y) echo yes;;
no|No|n|N) echo no;;
*) echo error
exit 1
esac
案例02:书写服务管理脚本,实现脚本开、关、重启与状态检查
不太推荐read方式
管理:nginxWebUI-3.4.0.jar
环境准备:jdk
[root@m01 /app/code/ngxwebui]#pwd
/app/code/ngxwebui
[root@m01 /app/code/ngxwebui]#ls
nginxWebUI-3.4.0.jar
[root@m01 /app/code/ngxwebui]#
提示:
服务类的脚本的名称尽量不要包含服务名称,否则,过滤的时候会把脚本过滤出来,还得排除
脚本:
#1、vars
choice=$1
codedir=/app/code/ngxwebui/
javaname=nginxWebUI-3.4.0.jar
#2、case
case "$choice" in
start)
#判断,如果没有运行,则启动
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 0 ];then
echo start
cd ${codedir}
nohup java -jar -Dfile.encoding=UTF-8 $javaname --server.port=8848 --project.home=$codedir &> /dev/null &
fi
;;
stop)
#如果进程已启动,则执行停止
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 1 ];then
echo stop
javapid=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}'`
kill $javapid
fi
;;
restart)
echo restart
#重启就是,停止再开启,$0脚本名称
sh $0 stop
sleep 1 #由于Java关闭需要时间,这里设置等待1秒,确保让它彻底关闭,再启动
sh $0 start
;;
status)
echo status
#判断服务是否运行
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 1 ];then
javapid=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}'`
echo "$javaname is running,pid: $javapid"
else
echo "$javaname is stopped"
fi
;;
*)
echo "Usage: $0 start|stop|restart|status"
exit 1
esac
2、函数
2.1 概述
把一堆代码,起个名字
对脚本中重复使用到的代码,设置函数,精简脚本的内容
2.2 格式与使用
格式1:
function 函数名() {
命令
return n #函数返回值
}
格式2:
function 函数名 {
命令
return n #函数返回值
}
格式3(推荐使用):
函数名() {
命令
return n
}
使用函数:函数名,注意不需要加()
例如:
[root@m01 /server/script/devops-shell]#vim 24.function.sh
function show() {
echo "funcion..."
echo "hello world"
}
show #调用函数
优化前面的服务脚本管理
[root@m01 /server/script/devops-shell]#vim 25.func.system_jar.sh
#1、vars
choice=$1
codedir=/app/code/ngxwebui/
javaname=nginxWebUI-3.4.0.jar
#2、函数定义
start() {
#判断,如果已经运行了,则不执行,没有运行,则启动
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 0 ];then
echo start
cd ${codedir}
nohup java -jar -Dfile.encoding=UTF-8 $javaname --server.port=8848 --project.home=$codedir &
fi
}
stop() {
#如果进程已启动,则执行停止
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 1 ];then
echo stop
javapid=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}'`
kill $javapid
fi
}
restart() {
echo restart
#重启就是,停止再开启,$0脚本名称
stop
sleep 1 #设置休眠时间为1秒,为了让它彻底关闭
start
}
status() {
echo status
#判断服务是否运行
java_process_count=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}' | wc -l`
if [ $java_process_count -eq 1 ];then
javapid=`ps -ef | grep "$javaname" | grep -v grep | awk '{print $2}'`
echo "$javaname is running,pid: $javapid"
else
echo "$javaname is stopped"
fi
}
#3、main
main() {
case "$choice" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status
;;
*)
echo "Usage: $0 start|stop|restart|status"
exit 1
esac
}
main
2.3 函数传参
函数传参与脚本传参类似,使用$xxx是形式
位置参数 | shell脚本中 | 函数中 |
---|---|---|
$n | 脚本的第n个参数 | 函数的第n个参数 |
$0 | 脚本的名称 | 脚本的名称 |
$# | 脚本的参数个数 | 函数的参数个数 |
$@、$* | 脚本的所有参数 | 函数的所有参数 |
使用格式: 函数名 参数
案例1:函数传参案例
[root@m01 /server/script/devops-shell]#vim 26.func.sh
show() {
echo $1
}
show hello
show $*
#执行
[root@m01 /server/script/devops-shell]#sh 26.func.sh world
hello
world
[root@m01 /server/script/devops-shell]#
3、个人函数库
把脚本中常用到的功能创建成函数
3.1 颜色
Linux命令行给字体加颜色的命令为:
echo -e "\E[1;31m红色字world\E[0m"
echo -e "\033[31m红色字world\033[0m"
效果:
解释:
\E或\033:表示要开启这种功能
[1;31m
[效果;颜色m
\E[0m 颜色设置结束
上述命令中,echo -e 可以识别转移字符(\n \t)
Linux中回车:\n
windows中回车:\r\n
10种效果:
颜色:
[root@m01 ~]#for n in {30..50}; do echo -e "\E[1;${n}mHello World\E[0m"; done
如下:
写成函数:例如
redecho() {
echo -ne "\E[5;31m" #-n:输出不换行
echo -n "$@"
echo -e "\E[0m"
}
greenecho() {
echo -ne "\E[1;32m"
echo -n "$@"
echo -e "\E[0m"
}
blueecho() {
echo -ne "\e[1;34m"
echo -n "$@"
echo -e "\e[0m"
}
案例1:自定义颜色函数
脚本:
[root@m01 /server/script/devops-shell]#vim func_diy.sh
#1、颜色类函数
redecho() {
echo -ne "\E[1;31m" #-n:输出不换行
echo -n "$@"
echo -e "\E[0m"
# echo -e "\e[5;31m $@ \e[0m"
}
greenecho() {
echo -ne "\E[1;32m"
echo -n "$@"
echo -e "\E[0m"
}
blueecho() {
echo -ne "\e[1;34m"
echo -n "$@"
echo -e "\e[0m"
使用:
[root@m01 /server/script/devops-shell]# . func_diy.sh
如图:
应用案例:
[root@m01 /server/script/devops-shell]#vim 28.ping_url_funcs.sh
#1、vars
if [ -f /server/script/devops-shell/func_diy.sh ];then
. /server/script/devops-shell/func_diy.sh
else
echo func_diy.sh not found
exit 1
fi
read -p '请输入域名:' url
#2、ping
ping -c 3 $url &> /dev/null
#3、判断
if [ $? -eq 0 ]
then
greenecho "域名$url可以ping通。"
else
redecho "域名$url ping不通"
fi
执行脚本,效果:
颜色的更多说明:https://man7.org/linux/man-pages/man4/console_codes.4.html
3.2 判断
判断参数个数
判断参数是否为数字
判断命令返回值
3.3 日志
给脚本创建日志
检查脚本关键步骤,执行情况。方便后期调试
比如:
定义名为log函数
使用:log 警告级别 "执行情况与做啥" 日志文件
日志内容:
年-月-日 时:分:秒[错误级别] "执行情况与做啥"
日志文件:/var/log/xxx.log
脚本:
[root@m01 /server/script/devops-shell]#vim func_log.sh
#日志函数
log() {
#vars
level=$1
msg=$2
logfile=$3
time=`date +%F_%T`
#检查日志目录
logdir=`dirname $logfile` #dirname取出目录,basename取出文件名
#logdir=${logfile%/*}
[ -d $logdir ] || mkdir -p $logdir
#写入日志
echo "[$time] [$level] [$msg]" >> $logfile
}
测试:
[root@m01 /server/script/devops-shell]#. func_log.sh
[root@m01 /server/script/devops-shell]#log ERROR 脚本运行正常 /var/log/test.log
[root@m01 /server/script/devops-shell]#cat /var/log/test.log
[2023-07-20_22:11:14] [ERROR] [脚本运行正常]
[root@m01 /server/script/devops-shell]#
4、必知必会命令
4.1 命令概述
脚本常用监控命令 | 用途 | 命令 |
---|---|---|
端口 | 一般用于检查端口是否存在,是否能连接 | 是否存在:ss -lntup | grep 端口 netstat -lntup | grep 端口 lsof -i:端口 是否能访问:telnet、nc、nmap |
进程 | 检查进程状态 | ps、top、iotop |
网络 | 检查连通性 | ping、iftop(流量)、dig(DNS)… |
web | http请求 | curl、wget |
系统全能 | atop(all) |
4.2 端口检查
1)是否存在
比如,检查80端口是否存在
[root@m01 ~]#ss -tnlup | grep 80
[root@m01 ~]#netstat -lntup | grep 80
[root@m01 ~]#lsof -i:80
2)能否访问
telnet:
-e:指定逃脱字符,遇到这个字符相当于ctrl+c
[root@m01 ~]#echo q | telnet -eq 192.168.10.61 80
Telnet escape character is 'q'.
Trying 192.168.10.61...
telnet: connect to address 192.168.10.61: Connection refused
[root@m01 ~]#echo $?
1
[root@m01 ~]#
执行命令结果是1,说明80端口不能访问
nc:
-z:无io模式,用于检查端口是否连通
[root@m01 ~]#nc -z 192.168.10.61 22
[root@m01 ~]#echo $?
0
[root@m01 ~]#
执行命令结果是0,说明22端口是通的
nmap:
[root@m01 ~]#nmap -p 192.168.10.61 22
PORT STATE SERVICE
22/tcp open ssh
[root@m01 ~]#
结果显示22端口是通的
4.3 进程检查
用ps、top命令
4.4 网络检查
ping命令:-c次数,ping几次,-w timeout 超时时间,等待响应的超时时间
iftop命令
4.5 web与api测试命令
1)curl命令
-v -L 跟随跳转
-H 修改请求头
-I 只显示响应头
-w 按照指定格式输出
-o 输出到指定文件或空
-s 一般用于管道,需要加上
使用:
#1、curl 获取状态码
# -s slient,安静模式,如果不适用,默认输出下载进度
# -o curl的输出到指定位置的文件
# -w 按照指定格式与内容输出,%{http_code}状态码,更多格式:man curl 搜索variable
获取状态码:
[root@m01 ~]#curl -s -w '%{http_code}\n' -o /dev/null www.baidu.com
200
[root@m01 ~]#
获取响应头:
[root@m01 ~]#curl -I www.baidu.com
POST:
输入用户名密码(ak id和securet)获取令牌token
通过令牌访问资源
-X 请求方法
-H 修改请求头
-d 请求报文主体
[root@m01 ~]#curl -s -X POST -H Content-Type:application/json-rpc 192.168.10.61/api_jsonrpc.php -d '{
"jsonrpc":"2.0"
"method":"user.login",
"params": {
"user": "Admin",
"password":"zabbix"
},
"id":1,
"auth":null
}'
[root@m01 ~]#
2)wget命令
-t 失败后,重复尝试次数
-T timeout,超时时间
-q 不显示wget输出
--spider 不下载文件,仅访问
例如:
[root@m01 ~]#wget -t 3 -T 1 -q --spider www.baidu.com
4.6 全能信息
atop安装:
[root@m01 ~]#yum install -y atop
[root@m01 ~]#systemctl enable atop
[root@m01 ~]#systemctl start atop
4.7 案例
案例1:检查指定的地址的端口是否可以访问
[root@m01 /server/script/devops-shell]#vim 29.check_port.sh
#1、vars
url=$1
port=$2
func=/server/script/devops-shell/funcs_diy.sh
logfunc=/server/script/devops-shell/funcs_log.sh
[ -f $logfunc ] && . $logfunc
if [ -f $func ];then
. $func
else
echo $func not found
exit 1
fi
#2、ping
ping -c1 $url &> /dev/null || {
redecho "$url无法访问"
exit 1
}
#3、telnet
echo q | telnet -eq $url $port &> /dev/null
if [ $? -eq 0 ];then
greenecho "$url $port 可以访问"
log INFO "$url $port OK" /var/log/port.log
else
redecho "$url $port 无法访问"
log ERROR "$url $port Failed" /var/log/port.log
fi
效果:
也可以使用nc:
# -w 超时时间
# -z 非交互式
if nc -w 1 -z $1 $2 ;then
echo "地址:$1 端口:$2 is ok"
else
echo "地址:$1 端口:$2 is failed"
fi
案例2:检查https证书是否过期,检查域名是否过期
获取ssl证书过期日期(以百度为例):
curl -Lv https://www.baidu.com -o /dev/null |& grep 'expire date'
* expire date: Aug 06 05:16:01 2023 GMT
[root@m01 ~]#
获取域名过期日期(以百度为例):
[root@m01 ~]#whois baidu.com | grep -i expiry
Registry Expiry Date: 2026-10-11T11:05:17Z
[root@m01 ~]#
把日期转为秒:
[root@m01 ~]#date +%s -d 'Aug 06 05:16:01 2023 GMT'
1691298961
[root@m01 ~]#
把当前日期转为秒,然后相减就得到,还有多少秒过期。再把秒转为日即可。
把ssl证书过期日期转为秒:
[root@m01 ~]#date -d "`curl -Lv https://www.baidu.com -o /dev/null |& grep 'expire date' | awk -F'date:' '{print $2}'`" +%s
1691298961
[root@m01 ~]#
把域名过期日期转为秒:
[root@m01 ~]# date -d "`whois baidu.com | grep -i expiry | awk -F'Date:' '{print $2}'`" +%s
1791716717
[root@m01 ~]#
把当前日期转为秒:
[root@m01 ~]#date +%s
1689866683
[root@m01 ~]#
分别相减即可。
最终脚本如下:
[root@m01 /server/script/devops-shell]#vim 30.chck_url_guoqi.sh
#1、vars
export LANG=en_US.UTF-8
url=$1
#加载自定义的函数文件
func=/server/script/devops-shell/funcs_diy.sh
log_func=/server/script/devops-shell/funcs_log.sh
[ -f $log_func ] && . $log_func
if [ -f $func ];then
. $func
else
echo "$func not found"
exit 1
fi
#检查
check_error() {
#2、check url
[[ $url =~ ^[a-zA-Z0-9]+\.[a-zA-Z]+$ ]] || {
redecho "$url 不可用"
}
#3、check_net
ping -c3 -i0.5 $url &>/dev/null || {
redecho "$url 无法访问"
exit 2
}
#4、check_cmd
which whois &>/dev/null || {
redecho "whois命令不存在"
exit 3
}
}
#检查域名过期
check_domain() {
#域名过期时间
expire_date=`whois $url | grep -Ei "expiry|expiration" | awk -F'Date: ' '{print $2}'`
#域名过期时间转为秒
expire_date_second=`date -d "${expire_date}" +%s`
#当前时间转为秒
date_now_second=`date +%s`
#两个秒数相减,除以60、60、24转为天数
date_expire_days=`echo "(${expire_date_second} - ${date_now_second})/60/60/24" | bc`
if [ ${date_expire_days} -le 30 ];then
redecho "$url 即将过期,还有${date_expire_days}天"
log ERROR "$url 即将过期,还有${date_expire_days}天" /var/log/url.log
else
greenecho "$url 可以安全使用,还有${date_expire_days}天"
log INFO "$url 可以安全使用,还有${date_expire_days}天" /var/log/url.log
fi
}
#检查证书过期
check_https() {
#域名过期时间
expire_date=`curl -v https://www.${url} |& grep -Ei "expire|expiration" | awk -F'date: ' '{print $2}'`
#域名过期时间转为秒
expire_date_second=`date -d "${expire_date}" +%s`
#当前时间转为秒
date_now_second=`date +%s`
#两个秒数相减,除以60、60、24转为天数
date_expire_days=`echo "(${expire_date_second} - ${date_now_second})/60/60/24" | bc`
if [ ${date_expire_days} -le 30 ];then
redecho "$url https证书即将过期,还有${date_expire_days}天"
log ERROR "$url https证书即将过期,还有${date_expire_days}天" /var/log/url.log
else
greenecho "$url https证书 可以安全使用,还有${date_expire_days}天"
log INFO "$url https证书 可以安全使用,还有${date_expire_days}天" /var/log/url.log
fi
}
#main
main() {
check_error
check_domain
check_https
}
main
测试如下图:
如果证书在本地,查看过期日期:
openssl x509 -in 证书文件 -noout -dates
notAfter就是过期日期
5、for循环
5.1 常用格式
1)格式1
最常见的格式
for 变量 in 清单(列表)
do
命令
done
例如:
for n in 1 2 3 4 5
do
ech $n
done
###########
for n in {1..10}
do
ech $n
done
##########
for n in {1..3} `ls /etc/|head -5` `seq 5`
do
echo $n
done
例如:计算1到100的和
sum=0
for n in {1..100}
do
sum=`echo "$sum+$n" | bc `
done
echo $sum
例如:
[root@m01 ~]#for n in `ls /etc/ | head -5`;do echo $n;done
abrt
adjtime
aliases
aliases.db
alternatives
[root@m01 ~]#
2)格式2
类似C语言格式的for循环,例如:
for((i=1;i<=10;i++))
do
echo $i
done
5.2 应用场景
格式1:通用场景,大部分场景可以使用
格式2:对数组循环使用
5.3 案例
案例:使用for循环在/test/目录下,通过随机小写1个字母加_test批量创建html文件。
比如文件名:adbjdueglv_test.html
生成随机字符:
1、uuidgen
2、mkpasswd -l 10 -d 0 -s 0 -C 0
-l:长度
-d:数字数量
-s:special,特殊字符
-C:大写字母
-c:小写字母
3、tr命令
tr -cd 'a-z' </dev/urandom | head -c10
-c:取反
-d:删除
/dev/urandom 字符设备,生成随机字符
4、date +%N | md5sum | cut -c1-10
date +%N | md5sum | head -c10
%N:纳秒
5、echo $RANDOM
范围:0-32767
echo $((RANDOM+1000000000))
脚本:
[root@m01 /server/script/devops-shell]#vim 31.random_files.sh
for n in {1..10}
do
str=`mkpasswd -l 10 -s 0`
filename=${str}_test.html
touch /tmp/$filename
done
6、while循环
6.1 格式
通用格式:
while 条件
do
命令
done
温馨提示:
while循环只会在满足条件后运行
案例01:使用while循环输出1-10
i=1
while [ $i -le 10 ]
do
echo $i
let i++
done
计算1到100的和:
[root@m01 ~]#echo {1..100} | tr ' ' '+' | bc
5050
[root@m01 ~]#
6.2 死循环
死循环:一直循环,直到用户手动中止或满足指定条件后退出
while true 或 while :
do
命令
done
例如:
[root@m01 ~]#while true ; do echo true; sleep 5 ;date ;done
true
Sat Jul 22 09:24:53 CST 2023
true
Sat Jul 22 09:24:58 CST 2023
案例:生产随机数字,判断数字是什么(1-100)
如果输入的数字比随机数大,提示大了。小,则提示小了。等于,提示等于,并退出程序
[root@m01 /server/script/devops-shell]#vim 34.guess_num.sh
#1、random
num=$((RANDOM%100+1)) #RANDOM范围:1-32767,对100取余,再加1,得到1-100的数
i=0
percent() {
if [ $i -le 5 ];then
echo "超过了99.99%的人,猜了$i次"
elif [ $i -le 10 ];then
echo "超过了90%的人,猜了$i次"
else
echo "超过了85%的人,猜了$i次"
fi
}
input() {
#2、vars
read -p "输入数字:" guess
}
check() {
#3、check
expr $guess + 1 &> /dev/null
[ $? -gt 1 ] && {
echo "请输入数字,重来"
exit 1
}
}
compare() {
#4、compare
if [ $guess -eq $num ];then
echo "猜对了"
percent
exit
elif [ $guess -gt $num ];then
echo "数字大了"
else
echo "数字小了"
fi
}
main() {
#5、while
while true
do
input
let i++
check
compare
done
}
main
6.3 while读取文件内容
方式1:采用exec读取文件内容,然后进入while循环
exec<FILE
while read line
do
命令
echo $line
done
方式2:使用cat读取文件,然后通过管道进入循环。不适用于有变量传递的场景
cat FILE | while read line
do
命令
echo $line
done
方式3:在while循环结尾done通过重定向输入
while read line
do
命令
echo $line
done<FILE
案例01:通过while read方式,统计ip.txt文件,ping下
#准备ip.txt文件
[root@m01 /server/script/devops-shell]#echo 192.168.10.61 >> ip.txt
[root@m01 /server/script/devops-shell]#echo 192.168.10.1 >> ip.txt
[root@m01 /server/script/devops-shell]#echo 192.168.10.2 >> ip.txt
[root@m01 /server/script/devops-shell]#echo 192.168.10.7 >> ip.txt
[root@m01 /server/script/devops-shell]#echo www.baidu.com >> ip.txt
[root@m01 /server/script/devops-shell]#echo baidu.com >> ip.txt
脚本如下:
[root@m01 /server/script/devops-shell]#vim 35.while_read_ping_ip.sh
#1、vars
ipfile=/server/script/devops-shell/ip.txt
#2、while
while read line
do
ping -c1 -i0.5 $line &> /dev/null
if [ $? -ne 0 ];then
echo "$line,网络不通"
else
echo "$line,网络通"
fi
done<$ipfile
方式2、方式3的区别:
[root@m01 /server/script/devops-shell]#vim while_read.sh
file=/server/script/devops-shell/ip.txt
i=0
j=0
#1、方法2:while+cat
echo "方式2:while + cat"
cat $file | while read ip
do
echo $ip
let i++
done
echo "次数:$i"
#2、方式3:while + 输入
echo "方式3:while + 输入"
while read ipa
do
echo $ipa
let j++
done<$file
echo "次数:$j"
测试结果:
显然,区别在于变量的作用范围,方式2的变量,离开开while循环体,则无法获取循环中修改过的值。
原因:
方式2:while read + 管道。在运行的时候因为管道,创建1个子shell,变量都存放在子shell中,子shell运行完成,消失了,而变量也没了
方式3:while + 输入重定向。运行的时候是与当前脚本在同一个shell中,所以变量保存了,可以继续使用。
在不涉及变量的情况下,方式2、方式3的效果是一样的,如果涉及变量,要使用方式3
案例02:分析NGINX访问日志(access.log),找出访问量最高的前5个ip及访问次数,ip访问次数大于200的,则通过防火墙屏蔽该ip
防DOS拒绝式攻击
DDOS分布式拒绝式服务攻击
CC基于http请求攻击
access.log日志内容格式如下:
101.226.61.184 - - [22/Nov/2015:11:02:00 +0800] "GET /mobile/sea-modules/gallery/zepto/1.1.3/zepto.js HTTP/1.1" 200 24662
以空格分隔,第一列就是ip
脚本:
[root@m01 /server/script/devops-shell]#vim 36.dos.sh
#1、vars
logfile=/server/script/files/access.log
tmpfile=/server/script/files/tmp.txt
#2、sort-uniq
awk '{print $1}' $logfile | sort | uniq -c | sort -rnk1 | head -5 >$tmpfile
#3、while
while read line
do
ip=`echo $line | awk '{print $2}'`
cnt=`echo $line | awk '{print $1}'`
iptables_cnt=`iptables -t filter -nL | grep -w $ip | wc -l`
if [ $cnt -ge 200 -a $iptables_cnt -eq 0 ];then
#判断次数大于200,且未屏蔽的才屏蔽,如果已经屏蔽则不需重复屏蔽
iptables -t filter -I INPUT -s $ip -j DROP
fi
done<$tmpfile
7、do-until循环
无论条件是否满足,都会执行1次。
直到型循环:一直循环,直到条件不满足
until 条件
do
命令
done
8、循环小结
循环 | 格式 | 应用场景 |
---|---|---|
for | for 变量 in 清单(列表);do 命令 ;done | 大部分使用 |
for((i=1;i<=10;i++));do 命令; done | 数组循环 | |
while | while 条件;do 命令; done | 死循环、读文件 |
until | until 条件;do 命令; done | 很少用 |