shell—100实例(20)

实例十一:【监控httpd进程】

需求:在服务器上,写一个监控脚本,要求如下:

1、每个10s去检测依次服务器上的httpd进程数,如果大于等于500的时候,就需要自动重启一下apache服务,并检测启动是否成功?

2、若没有正常启动还需再一次启动,最大不成功数超过5次,则不需要再检测!

3、如果启动成功后,1分钟后再次检测httpd进程数,若正常则重复之前操作(每隔10s检测一次),若还是大于等于500,那么放弃重启并退出该脚本。

提示:pgrep -l httpd 或者ps -C httpd --no-heading 检测进程

#!/bin/bash
#moniter httpd process...
#
declare -i sum=1
while [ $sum -eq 1 ]
do
        flag=''
        count=`pgrep -l httpd|wc -l`
        if [ $count -ge 10 ];then
                declare -i I=1
                while [ $I -lt 5 ]
                do
                /etc/init.d/httpd restart
                if [ $? -eq 0 ];then
                        echo "服务重启成功!"
                        flag=true
                        break
                else
                        echo "服务重启失败!"
                        I=$[ $I + 1 ]
                        flag=false
                fi
                done

        fi
        if [ $I -eq 6 ]&&[ $false == 'false' ];then
                echo 'httpd service warnning!' | mail -s "httpd service warnning" -t root@localhost -a From:root@localhost
                exit 5
        fi
        if [ $flag == 'true' ];then
                sleep 4
                count=`pgrep -l httpd|wc -l`
                if [ $count -ge 100 ];then
                #       echo 'httpd service warnning!' | mail -s "httpd service warnning" -t root@localhost -a From:root@localhost
                        exit 7
                fi
        fi
done

脚本亮点:

1、使用标识变量$flag来标记服务重启结果,若成功,则$flag=true;若失败,则$flag=false;便于后续的条件判断

2、sleep 10 >此命令作用是在脚本执行过程中,如果遇到sleep命令,则会根据此命令后续的参数,"进程睡眠”多长时间后再继续执行后续进程

【脚本二】

#!/bin/bash
check_service()
{
        c=0
        for i in `seq 1 5`
        do
        /usr/local/apache2/bin/apachectl -k restart 2> /tmp/httpd.err
        if [ ! $? -eq 0 ]
        then
           c=$[$c+1]
        else
           break
        fi
        done
        if [ $c -eq 5 ]
        then
        python mail.py "123@qq.com " "apache进程数量大于500,重启失败。" "`head -1 /tmp/httpd.err`"
        exit
        fi
}
 
while :
do
        n=`ps -C httpd --no-heading|wc -l`
        if [ $n -ge 500 ]
        then
                check_service
                sleep 60
                n_new=`ps -C httpd --no-heading|wc -l`
                if [ $n_new -ge 500 ]
                then
                        python mail.py "123@qq.com " "apache重启一分钟后进程数量仍然大于500" "请登录服务器排查问题"
                        exit
                fi
        fi
 
sleep 10
done

脚本亮点:

1、由于此需求是需要根据条件不断检查并重启服务的,所以会有一部分模块需要重复调用

2、使用函数将检查服务、重启服务的需求模块化,使得脚本更加简洁

 

实例十二:【封IP】

需求:根据web服务器上的访问日志,把一些请求量非常高的ip给拒绝掉!并且每隔半小时把不再发起请求或者请求量很少的ip解封。

假设:1、一分钟内请求量高于100次的ip视为不正常请求。2、访问日志路径为/data/logs/access_log

核心要点:1、统计ip访问次数、排序  2、如何标记每隔半小时  3、iptables计数器是一个重要的判断指标  4、函数(封ip、解IP)

#!/bin/bash
block_ip
{
t1=`date -d "-1 min" +%Y:%H:%M`
log/data/logs/access_log
egrep "$t1:[0-9]+" $log > /tmp/tmp_last_min.log
awk '{print $1}' /tmp/tmp_last_min.log |sort -n |uniq -c|sort -n |awk '$1>100 {print $2}' > /tmp/bad_ip.list
n=`wc -l /tmp/bad_ip.list|awk '{print $1}'`
if [ $n -ne 0 ]
then
        for ip in `cat /tmp/bad_ip.list`
        do
                iptables -I INPUT -s $ip -j REJECT
        done
fi
}
 
unblock_ip()
{
        iptables -nvL INPUT |sed '1d' |awk '$1<5 {print $8}' > /tmp/good_ip.list
        n=`wc -l /tmp/good_ip.list|awk '{print $1}'`
        if [ $n -ne 0 ]
        then
        for ip in `cat /tmp/good_ip.list`
        do
                iptables -D INPUT -s $ip -j REJECT
        done
        fi
        iptables -Z
}
 
t=`date +%M`
if [ $t == "00" ] || [ $t == "30" ]
then
        unblock_ip
        block_ip
else   
        block_ip
fi

脚本亮点:

1、由于没有实验环境,此题答案是直接从其他博主拷贝过来的

2、awk '{print $1}' /tmp/tmp_last_min.log |sort -n |uniq -c|sort -n |awk '$1>100 {print $2}' > /tmp/bad_ip.list >此指令的意思如下:获取文档/tmp/tmp_last_min.log中每一行的第一列内容,然后根据首个数字进行排序,然后统计相同的项,然后在根据相同项的数量进行排序,最后选择出现次数大于100的项,也就是ip,并把这些ip导入到/tmp/bad_ip.list文档中

 

实例十三:【算数字】

需求:1、请仔细查看如下几个数字的规律,并使用shell脚本输出后面的十个数字。10 31 53 77 105 141...

提示:计算两个数值之间的差值

#!/bin/bash
#creat some number with some rule!
#
declare -i tip=141
for i in `seq 5 15`
do
        tip=$[$tip+20+2**$i]
        echo "$tip"
        echo "........."
done

脚本亮点:

1、使用seq命令生成特定的数列

【脚本二】

#!/bin/bash
x=10
y=21
for i in `seq 0 15`;
do
    echo $x;
    x=$[$x+$y]
    z=$[2**$i]  #(求幂)
    y=$[$y+$z]
done

实例十四:【查用户】

需求:看看你的Linux系统中是否有自定义用户(普通用户),若是有,一共有几个?

提示:1、CentOS6中,自定义用户的uid>=500  2、CentOS7中,自定义用户的uid>=1000

cat /etc/passwd|awk -F: '$3 >=500 {print $3}'|wc -l

脚本亮点:1、awk -F: '$3 >=500 {print $3}' >此命令将管道传过来的参数,使用 ":"进行分隔,并且匹配第三字段大于等于500的行,然后将符合的行的第三个字段打印出来

【脚本二】

#!/bin/bash
v=`awk -F 'release ' '{print $2}' /etc/redhat-release |cut -d '.' -f1`
user()
{
        if [ $1 -eq 0 ]
        then
                echo "系统没有自定义的用户"
        else
                echo "系统存在自定义用户。有$1个"
        fi
}
 
case $v 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 "脚本出错"
        ;;
esac

脚本亮点:

1、此脚本先对系统版本进行判断

2、然后使用函数进行自定义用户的判断

 

实例十五:【检测磁盘】

需求:检测所有磁盘分区使用率和inode使用率并记录到以当天日期为命名的日志文件里,当发现某个分区容量或者inode使用量大于85%时,发邮件通知自己

提示:1、df -i  2、df  3、date +%F

 

#!/bin/bash
#check the usage space of the disks
#
num=`df|grep "/dev/sda1"|awk '{print $5}'`      #获取/dev/sda1分区的磁盘使用率
num1=`df -i|grep "/dev/sda1"|awk '{print $5}'`  #获取/dev/sda1分区的inode号使用率
num_disk=`echo "$num"|awk -F% '{print $1}'`     #去掉使用率中的百分号%
num1_inode=`echo "$num1"|awk -F% '{print $1}'`  #去掉使用率中的百分号%
if [ $num_disk -ge 5 ];then
        echo "warnning!!!"
else
        echo "xxx"
fi
[ $num1_inode -ge 1 ]&&echo "SOS"||echo "normal"

脚本亮点:

1、[ $num1_inode -ge 1 ]&&echo "SOS"||echo "normal" >此命令是if命令的简化版,当[ $num1_inode -ge 1]成立时,会执行&&后面的命令,也就是echo "SOS";但当[ $num1_inode -ge 1]不成立时,则会执行 "||"后面的命令,也就是e'cho "normal"

【脚本二】

#!/bin/bash
dir=/tmp/disk
d=`date +%F`
m=123@123.com
[ -d $dir ] || mkdir $dir
df >> $dir/$d.log
df -i >> $dir/$d.log
 
df|sed '1d' |awk -F ' +|%' '$5>=85 {print $7}' > $dir/df.tmp
df -i|sed '1d' |awk -F ' +|%' '$5>=85 {print $7}' > $dir/df_i.tmp
n1=`wc -l $dir/df.tmp|awk '{print $1}'`
n2=`wc -l $dir/df_i.tmp|awk '{print $1}'`
 
tag=0
if [ $n1 -gt 0 ]
then
        if [ $n2 -gt 0 ]
        then
                tag=11
        else
                tag=10
        fi
else
        if [ $n2 -gt 0 ]
        then
                tag=01
        else
                tag=00
        fi
 
fi
 
case $tag in
        11)
        python mail.py $m  "磁盘空间和inode使用率高于85" "`cat $dir/df.tmp $dir/df_i.tmp|xargs`"
        ;;
        10)
        python mail.py $m "磁盘空使用率高于85" "`cat $dir/df.tmp|xargs`"
        ;;
        01)
        python mail.py $m "磁盘inode使用率高于85" "`cat $dir/df_i.tmp|xargs`"
        ;;
        *)
        ;;
esac

 

实例十六:【检测新文件】

需求:有一台服务器作为web应用,有一个目录(/data/web/attachment)不定时地会被用户上传新的文件,但是不知道什么时候会上传。所以,需要我们每5分钟做一次检测是否有新文件生成。请写一个shell去完成检测。检测完成后若是有新文件,还需要将文件的列表输出到一个按年、月、日、时、分为名字的日志里。

提示:1、find -mmin -5  2、date +%Y%m%d%H%M

#!/bin/bash
basedir=/tmp/
t=`date +%Y%m%d%H%M`
 
find $basedir/ -type f -mmin -5 > /tmp/file.list
n=`wc -l /tmp/file.list|awk '{print $1}'`
if [ $n -gt 0 ]
then
        mv /tmp/file.list /tmp/$t.list
fi

脚本亮点:

1、find $basedir/ -type f -mmin -5 > /tmp/file.list >此命令将文档修改时间小于当前时间五分钟的文档名称导出到/tmp/file.list文档中

 

实例十七:【最常用的命令】

需求:写一个shell脚本来看看你使用最多的命令是那些,列出你最常用的命令top10

提示:1、history 或者~/.bash_history  2、sort、uniq

#!/bin/bash
#
#count=`history | awk '{print $2}' |sort |uniq -c|sort -nr|head`
count=`cat ~/.bash_history| awk '{print $2}' |sort |uniq -c|sort -nr |head -n 10`
echo "$top1 $count"

命令解析:

1、sort -nr >按照每一行第一个数字进行反向排序,即有小到大

 

实例十八:【统计文件大小】

需求:假如需要每小时都去执行一个脚本。在脚本中实现这样的功能,当时间是0点和12点时,需要将目录/data/log/下的文件全部清空,注意只能清空文件内容而不能删除文件。而其他时间只需要统计一下每个文件的大小,一个文件一行,输出到一个按日期和时间为名字的日志里。需要考虑/data/log/目录下的二级、三级、...等子目录里面的文件。

提示:

1、find 列出所有文件  2、date +%H  3、>file清空文件

【此脚本为其他博主写的】

#!/bin/bash
dir=/tmp/log_stat
t=`date +%d%H`
t1=`date +%H`
logdir=/data/log
 
[ -f $dir/$t.log ] && rm -f $dir/$t.log
[ -d $dir ] || mkdir $dir
 
 
if [ $t == "00" -o $t == "12" ]
then
        for f in `find $logdir/ -type f`
        do
                > $f
        done
else
        for f in `find $logdir/ -type f`
        do
                du -sh $f >> $dir/$t.log
        done
fi

脚本解析:

1、第一步先获取相应的时间并赋予变量

2、[ -f $dir/$t.log ] && rm -f $dir/$t.log >检查文档$dir/$t.log是否存在,若存在则删除文档;若不存在则不做操作

3、[ -d $dir ] || mkdir $dir >检查目录$dir是否存在,若存在,则不做操作;若不存在,则创建该目录

4、>$f  >此命令的意思是将空内容覆盖原文档$f的内容,即清空文档$f的内容

5、du -sh $f >> $dir/$t.log >此命令是读取文档$f的大小信息,并将信息追加到文档$dir/$t.log中

 

实例十九:【计算数字个数】

需求:计算文档a.txt中每一行出现的数字个数并且要计算一下整个文档中一共出现了几个数字。例如a.txt内容如下:

12aa*lkjskdj  alskdflkskdjflkjj

我们脚本名字为ncount.sh,运行它时:bash ncount.sh a.txt

输出结果应该为:2  0   sum:2

提示:1、sed把非数字字符删除、计算长度  2、for循环计算总和

#!/bin/bash
#coute the number string in 句子
#
declare -i total=0
num=`sed 's/[^0-9]//g' a.txt`
echo "$num"
for h in $num
do
        mh=`echo "$h"|wc -L`
        echo "$mh"
        total=$[$total+$mh]
done
echo
#total=`echo "$num"|wc -L`
echo "sum:$total"

脚本解析:

1、num=`sed 's/[^0-9]//g' a.txt` >将a.txt中每一行非数字的去掉,并保存在变量num中

【脚本二】

#!/bin/bash
sum=0
while read line
do
        line_n=`echo $line|sed 's/[^0-9]//g'|wc -L`
        echo $line_n
        sum=$[$sum+$line_n]
done < $1
echo "sum:$sum"

脚本解析:

1、此处使用while循环来遍历a.txt的内容

2、done < $1   >此处的位置变量就是a.txt

 

实例二十:【对比文件差异】

需求:有两台Linux服务器A和B,假如A可以直接ssh到B,不用输入密码。A和B都有一个目录叫/data/web/,这下面有很多文件,当然我们不知道具体有几层子目录,假若之前A和B上,该目录下的文件都是一模一样的。但是现在不确定是否一致了。故须要写一个脚本实现检测A机器和B机器/data/web/目录下文件的异同,我们以A机器上的文件做为标准。比如假如B机器少了一个a.txt文件,那么我们应该能够检测出来,或者B机器上的b.txt文件有过改动,我们也应该能够检测出来(B机器上多了文件不用考虑)。

提示:

1、md5sum file

dir=/data/web
[ -f /tmp/md5.list ] && rm -f /tmp/md5.list
find $dir/ -type f > /tmp/file.list
while read line
do
    md5sum $line  >> /tmp/md5.list
done < /tmp/file.list
 
scp /tmp/md5.list B:/tmp/
[ -f /tmp/check_md5.sh ] && rm -f /tmp/check_md5.sh
 
cat >/tmp/check_md5.sh << EOF
#!/bin/bash
dir=/data/web
n=\`wc -l /tmp/md5.list|awk '{print \$1}'\`
for i in \`seq 1 \$n\`
do
    file_name=\`sed -n "\$i"p /tmp/md5.list |awk '{print \$1}'\`
    md5=\`sed -n "\$i"p /tmp/md5.list|awk '{print \$2}'\`
    if [ -f \$file_name ]
    then
    md5_b=\`md5sum \$file_name\`
    if [\$md5_b != \$md5 ]
    then
        echo "\$file_name changed."
    fi
    else
    echo "\$file_name lose."
    fi
done
EOF
scp /tmp/check_md5.sh B:/tmp/
ssh B "/bin/bash /tmp/check_md5.sh"

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值