【Shell】Shell脚本实例二

只愿长相守 提交于 2020-02-14 02:20:29

Shell脚本实例二

1. 通过shell脚本封请求数异常的IP
2. 备份MySQL数据库
3. 通过shell脚本+expect批量发布代码到多台web服务器
4. 定时执行Linux shell脚本实现SFTP定时上传下载文件
5. 检测网卡流量

  • 1.通过shell脚本封请求数异常的IP
需求:
1.通过分析访问日志,将1分钟内请求超过100次的IP封掉
2.每半小时将不再请求或请求量很小的IP解封
3.访问日志路径/data/logs/access.log

访问日志示例:
192.168.234.1 - - [22/Oct/2019:20:34:07 +0800] "GET / HTTP/1.1" 200 53570 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" "-"
192.168.234.1 - - [22/Oct/2019:20:34:07 +0800] "GET /wp-includes/css/dist/block-library/style.min.css?ver=5.2.3 HTTP/1.1" 301 169 "http://www.blog.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" "-"
192.168.234.1 - - [22/Oct/2019:20:34:07 +0800] "GET /wp-includes/css/dist/block-library/theme.min.css?ver=5.2.3 HTTP/1.1" 301 169 "http://www.blog.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36" "-"

脚本思路:
1.通过data命令匹配日志文件中第二列过滤出前1分钟的访问记录,将请求数大于100的IP记录到临时文件ban_ip.list中
2.通过for循环遍历临时文件ban_ip.list每行的IP地址,使用iptables禁掉
3.通过iptables -nvL INPUT命令查看第一列(pkts)被封IP发送数据包的个数,当发送的数据包小于5时,解封(每半小时执行一次)

#!/bin/bash
#定义封IP方法
function ban_ip()
{
    t=`date -d "-1 min" +%Y:%H:%M`
    log=/data/logs/access.log
    #当IP前一分钟请求数大于100,记录到临时文件
    egrep "$t:[0-9]+" $log|awk '{print $1}'|sort -n|uniq -c|sort -n|awk '$1>100 {print $2}' >/tmp/ban_ip.list
    #当记录IP的临时文件不为空时,开始封IP
    ban_n=`wc -l /tmp/ban_ip.list|awk '{print $1}'`
    if [ $ban_n -ne 0 ]
    then
	for ip in `cat /tmp/ban_ip.list`
	do
	  iptables -I INPUT -s $ip -j REJECT
	done
    fi
}
#定义解封IP的方法
function allow_ip()
{
    #将发送数据包小于5的被封IP记录到临时文件
    iptables -nvL INPUT|sed '1d'|awk '$1<5 {print $8}' >/tmp/allow_ip.list
    #当临时文件不为空时,开始解封IP
    allow_n=`wc -l /tmp/allow_ip.list|awk '{print $1}'`
    if [ $allow_n -ne 0 ]
    then
	for ip in `cat /tmp/allow_ip.list` 
	do
	  iptables -D INPUT -s $ip -j REJECT
	done
    fi
    #清空iptables计数器(记录数据包那一列的值将被清零)
    iptables -Z
}
#执行封IP操作,但每半小时才执行一次解封IP操作
d=`date +%M`
if [ $d == "00" ]||[ $d == "30" ]
then
    allow_ip
    ban_ip
else
    ban_ip
fi

补充:
1.将脚本加入crontab任务计划设置每分钟执行一次即可
2.日志文件需要每天切割一次(因为通过年::分的方式过滤出的结果,如日志不每天做切割,过滤出的前一分钟IP访问记录将不只是今天的数据)



  • 2.备份MySQL数据库
场景:一台MySQL服务器,跑着5个数据库,在没有做主从的情况下,需要对这5个库进行备份

需求:
1)每天备份一次,需要备份所有的库
2)把备份数据存放到/data/backup/3)备份文件名称格式示例:dbname-2019-11-23.sql
4)需要对1天以前的所有sql文件压缩,格式为gzip
5)本地数据保留16)需要把备份的数据同步到远程备份中心,假如本机可以直接通过rsync命令同步,同步目标地址为192.168.234.125,数据存放目录:/data/mysqlbak/
7)远程备份数据要求保留1个月

脚本:
#!/bin/bash
mysqldump="/usr/local/mysql/bin/mysqldump"
bakdir="/data/backup"
bakuser="backup"
passwd="backup123"
d1=`date +%F`
d2=`date +%d`

#将后面所有的输出都写入到日志
exec &> tmp/bak.log
echo "mysql bakup begin at `date`"

#循环遍历数据库并导出
for db in db1 db2 db3 db4 db5
do
    $mysqldump -u$bakuser -p$passwd $db > $bakdir/$db-$d1.sql
done

#压缩一天前的备份文件
find $bakdir -type f -name "*.sql" -mtime +1 |xargs gzip

#删除一周前的被封文件
find $bakdir -type f -mtime +7 |xargs rm

#把当天的备份文件同步到远程机器
for db in db1 db2 db3 db4 db5
do
    rsync -a $bakdir/$db-$d1.sql rsuser@192.168.234.125::/data/mysqlbak/$db-$d2.sql
done

echo "mysql bakup end at `date`"

补充:
1.远程机器存放的备份文件以库名-日期的具体日命名,就实现了自动保留30天(比如15号备份的文件db1-15.sql下个月1号的备份文件将会覆盖该文件)
2.当数据库较大时,使用mysqldump备份速度会非常慢,这时该使用xtarbackup工具备份或mysql主从复制


  • 3.通过shell脚本+expect批量发布代码到多台web服务器
前提:
1)提供一个存放所有web服务器的IP列表文件ip.list
2)假设所有web服务器上有一个普通用户user,密码为user123,该用户为同步代码用户
3)每次代码上线会提供一个文件列表file.list(即要更改的文件的列表)

脚本:
#/bin/bash
#提醒用户,是否更新了要上线的代码列表文件
read -p "你是否已经更新了文件列表./file.list?确认请输入y或者Y,否则按其他任意键退出脚本。" c
#如果直接按回车,也会退出脚本
if [ -z "$c" ]
then
 	exit 1
fi

if [ $c == "y" -o $c == "Y" ]
then
 	echo "脚本将在2秒后,继续执行。"
 	#每秒输出一个.共输出两个.
 	for i in 1 2
 	do
 		echo -n "."
		 sleep 1
 	done
 	echo
else
 	exit 1
fi

#判断有无./rsync.exp文件
[ -f ./rsync.exp ] && rm -f ./rsync.exp
#定义rsync.exp
cat >./rsync.exp <<EOF
#!/usr/bin/expect
set passwd "user123"
set host [lindex \$argv 0]
set file [lindex \$argv 1]
spawn rsync -avR --files-from=\$file / user@\$host:/
expect {
	"yes/no" {send "yes\r"}
	"password:" {send \$passwd\r}
}
expect eof
EOF
chmod a+x ./rsync.exp

#定义检测文件是否存在的函数
if_file_exist()
{
 	if [ ! -f $1 ]
 	then
 		echo "文件$1不存在,请检查。"
		 exit 1
}

#ip.list为所有WEB机器的ip列表
#file.list为要同步的文件列表
if_file_exist ./ip.list
if_file_exist ./file.list
for ip in `cat ./ip.list`
do
 	./rsync.exp $ip ./file.list
done
#善后处理
rm -f ./rsync.exp

注意:在每台web服务器上创建的代码同步用户需要有代码所在目录的写入权限


  • 4.定时执行Linux shell脚本实现SFTP定时上传下载文件
一:定时任务
执行命令:crontab -e
10 12 * * * sh /home/uploadFile.sh

二:SFTP上传下载的shell脚本
#!/bin/bash
IP=1.1.1.1
PORT=22
USER=username
PASSWORD=password

#待上传文件根目录
CLIENTDIR=/client/upload
#SFTP目录
SEVERDIR=/server/upload
#待上传文件名
FILE=filename

lftp -u ${USER},${PASSWORD} sftp://${IP}:${PORT} <<EOF
cd ${SEVERDIR}/
lcd ${CLIENTDIR}
put ${FILE}
by
EOF

完整的sftp下载脚本如下:
#!/bin/bash
IP=1.1.1.1
PORT=22
USER=username
PASSWORD=password

#待接收下载文件根目录
CLIENTDIR=/client/download
#服务器待下载目录
SEVERDIR=/server/download
#待下载文件名
FILE=filename

lftp -u ${USER},${PASSWORD} sftp://${IP}:${PORT} <<EOF
cd ${SEVERDIR}/
lcd ${CLIENTDIR}
get ${FILE}
by
EOF

如果提示lftp命令无效,执行命令:yum install lftp -y,进行安装


  • 5.检测网卡流量
需求:
每分钟检测一次网卡流量(假设网卡名称为ens33),将结果记录到一个日志中,每个日志文件只记录当天的网卡流量信息,保留30天

脚本思路:
通过命令sar -n DEV 1 591分钟内的平均进出流量
日志名称以日_时.log命名,下个月会覆盖本月文件,实现保留30天

#!/bin/bash
dir=/tmp/sarlog
file=$dir/`date +%d_%H`.log
t=`date +%F_%T`

[ -d $dir ] || mkdir -p $dir

sar -n DEV 1 59|grep Average|grep ens33 > /tmp/sar.tmp

exec >> $file
echo $t
awk '{print "ens33 input: "$5"kB""\n""ens33 output: "$6"kB"}' /tmp/sar.tmp
echo "#####################"


执行结果:
[root@linux shell]# sh test.sh 
[root@linux shell]# cat /tmp/sarlog/05_20.log 
2019-12-05_20:34:19
ens33 input: 0.06kB
ens33 output: 0.07kB
#####################
2019-12-05_20:37:03
ens33 input: 0.00kB
ens33 output: 0.01kB
#####################

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!