通过shell脚本监控httpd进程数
需求:
1.每10秒检测一次httpd进程数,当大于500时需要自动重启一下Apache服务,并检测是否重启成功
2.如果重启失败,再重启一次,最大失败次数超过5次立即发邮件通知管理员,并且脚本不再继续运行
3.如果重启成功,1分钟之后再次检测httpd进程,如果正常还是继续执行之前的操作(每10秒重启一次),若进程数还是大于500,则邮件通知管理员,并且该检测脚本不再继续运行
脚本思路:
通过 pgrep -l httpd|wc -l或 ps -C httpd --no-heading|wc -l检测进程数,进行判断
#!/bin/bash
#定义重启Apache服务的脚本
function check_apache()
{
count=0
for i in `seq 1 5`
do
/usr/local/apache/bin/apachectl -k restart 2>/tmp/apache.err
#如果Apache重启不成功,则计数变量加1
if [ ! $? -eq 0 ]
then
count=$[$count+1]
else
break
fi
done
#如果Apache重启失败5次,则发送邮件通知管理员
if [ $count -eq 5 ]
then
python mail.py asnfy@qq.com "Apache进程数大于500,重启失败" "`head -1 /tmp/apache.err`"
exit
fi
}
while :
do
#每10秒检测一次httpd进程数
n=`ps -C httpd --no-heading|wc -l`
#如果大于500,则重启
if [ $n -ge 500 ]
then
check_apache
sleep 60
#重启1分钟后进程数仍然大于500,则通知管理员并退出脚本
n1=`pgrep -l httpd|wc -l`
if [ $n1 -ge 500 ]
then
python mail.py asnfy@qq.com "Apache重启1分钟后进程数仍然大于500" "请登录服务器排查问题"
exit
fi
fi
sleep 10
done
通过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访问记录将不只是今天的数据)
统计系统中的普通用户数量
需求:
1.统计linux系统中的普通用户有多少个
脚本思路:
1.通过配置文件/etc/passwd第三列的uid判断是否为普通用户
2.在centos5/6版本中,uid大于等于500即为普通用户,centos7版本中,uid大于等于1000即为普通用户
3.通过配置文件/etc/redhat-release文件判断centos版本
#!/bin/bash
#获取centos版本号
version=`awk -F 'release ' '{print $2}' /etc/redhat-release |cut -d '.' -f1`
function user()
{
if [ $1 -eq 0 ]
then
echo "系统中没有普通用户"
else
echo "系统中普通用户数为:$1"
fi
}
case $version in
5|6)
n=`awk -F ':' '$3>=500' /etc/passwd |wc -l`
user $n
;;
7)
n=`awk -F ':' '$3>=1000' /etc/passwd |wc -l`
user $n
;;
*)
echo "该脚本只支持centos5/6/7版本."
;;
esac