├── README.md └── codes ├── 1.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md ├── 15.md ├── 16.md ├── 17.md ├── 18.md ├── 19.md ├── 2.md ├── 20.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── 7.md ├── 8.md └── 9.md /README.md: -------------------------------------------------------------------------------- 1 | #### 51cto订阅专栏《实战:20天精通Linux shell脚本》 2 | 专栏地址: [http://blog.51cto.com/cloumn/detail/22](http://blog.51cto.com/cloumn/detail/22) 3 | 4 | 案例1: [备份MySQL数据库](https://github.com/aminglinux/shell20/blob/master/codes/1.md) 5 |
6 | 案例2: [监控Nginx服务器502](https://github.com/aminglinux/shell20/blob/master/codes/2.md) 7 |
8 | 案例3: [批量添加用户](https://github.com/aminglinux/shell20/blob/master/codes/3.md) 9 |
10 | 案例4: [自动封/解封IP](https://github.com/aminglinux/shell20/blob/master/codes/4.md) 11 |
12 | 案例5: [监控磁盘使用率](https://github.com/aminglinux/shell20/blob/master/codes/5.md) 13 |
14 | 案例6: [检测两台机器上文件的差异](https://github.com/aminglinux/shell20/blob/master/codes/6.md) 15 |
16 | 案例7: [监控MySQL主从状态](https://github.com/aminglinux/shell20/blob/master/codes/7.md) 17 |
18 | 案例8: [傻瓜运维脚本](https://github.com/aminglinux/shell20/blob/master/codes/8.md) 19 |
20 | 案例9: [监控网卡流量](https://github.com/aminglinux/shell20/blob/master/codes/9.md) 21 |
22 | 案例10: [检测域名是否到期](https://github.com/aminglinux/shell20/blob/master/codes/10.md) 23 |
24 | 案例11: [人员分组](https://github.com/aminglinux/shell20/blob/master/codes/11.md) 25 |
26 | 案例12: [shell多线程备份数据库](https://github.com/aminglinux/shell20/blob/master/codes/12.md) 27 |
28 | 案例13: [监控CDN各节点是否正常](https://github.com/aminglinux/shell20/blob/master/codes/13.md) 29 |
30 | 案例14: [为LAMP网站增加项目](https://github.com/aminglinux/shell20/blob/master/codes/14.md) 31 |
32 | 案例15: [格式化输出xml文件](https://github.com/aminglinux/shell20/blob/master/codes/15.md) 33 |
34 | 案例16: [自动化运维-批量关Tomcat服务](https://github.com/aminglinux/shell20/blob/master/codes/16.md) 35 |
36 | 案例17: [归档老日志](https://github.com/aminglinux/shell20/blob/master/codes/17.md) 37 |
38 | 案例18: [找出磁盘忙的真凶](https://github.com/aminglinux/shell20/blob/master/codes/18.md) 39 |
40 | 案例19: [分析Tomcat日志](https://github.com/aminglinux/shell20/blob/master/codes/19.md) 41 |
42 | 案例20: [自动化运维-代码上线](https://github.com/aminglinux/shell20/blob/master/codes/20.md) 43 | 44 | -------------------------------------------------------------------------------- /codes/1.md: -------------------------------------------------------------------------------- 1 | #### 案例1参考脚本 2 | 3 | ``` 4 | #!/bin/bash 5 | ##该脚本用来备份本机数据库 6 | ##本地保留一周,远程保留一个月 7 | ##作者:阿铭 8 | ##日期:2018-09-15 9 | ##版本:v0.1 10 | 11 | mysqldump="/usr/local/mysql/bin/mysqldump" 12 | bakuser="backup" 13 | passwd="34KpmyzUq" 14 | bakdir="/data/backup" 15 | remote_dir="rsync://10.10.20.100/mysqlbak" 16 | d1=`date +%F` 17 | d2=`date +%d` 18 | 19 | #定义日志 20 | exec &> /tmp/mysql_bak.log 21 | 22 | echo "mysql backup begin at `date`" 23 | 24 | #对所有数据库进行遍历 25 | for db in db1 db2 db3 db4 db5 26 | do 27 | $mysqldump -u$bakuser -p$passwd $db >$bakdir/$db-$d1.sql 28 | done 29 | 30 | #对1天前的所有sql文件压缩 31 | find $bakdir/ -type f -name "*.sql" -mtime +1 |xargs gzip 32 | 33 | #查找一周以前的老文件,并删除 34 | find $bakdir/ -type f -mtime +7 |xargs rm 35 | 36 | #把当天的备份文件同步到远程 37 | for db in db1 db2 db3 db4 db5 38 | do 39 | rsync -a $bakdir/$db-$d1.sql $remote_dir/$db-$d2.sql 40 | done 41 | 42 | echo "mysql backup end at `date`" 43 | ``` 44 | -------------------------------------------------------------------------------- /codes/10.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | #检测域名是否过期 5 | #作者:阿铭 6 | #日期:2018-10-10 7 | #版本:v0.2 8 | 9 | mail_u=admin@admin.com 10 | #当前日期时间戳,用于和域名的到期时间做比较 11 | t1=`date +%s` 12 | 13 | #检测whois命令是否存在,不存在则安装jwhois包 14 | is_install_whois() 15 | { 16 | which whois >/dev/null 2>/dev/null 17 | if [ $? -ne 0 ] 18 | then 19 | yum install -y jwhois 20 | fi 21 | } 22 | 23 | notify() 24 | { 25 | e_d=`whois $1|grep 'Expiry Date'|awk '{print $4}'|cut -d 'T' -f 1` 26 | #如果e_d的值为空,则过滤关键词'Expiration Time' 27 | if [ -z "$e_d" ] 28 | then 29 | e_d=`whois $1|grep 'Expiration Time'|awk '{print $3}'` 30 | fi 31 | #将域名过期的日期转化为时间戳 32 | e_t=`date -d "$e_d" +%s` 33 | #计算一周一共有多少秒 34 | n=`echo "86400*7"|bc` 35 | e_t1=$[$e_t-$n] 36 | e_t2=$[$e_t+$n] 37 | if [ $t1 -ge $e_t1 ] && [ $t1 -lt $e_t ] 38 | then 39 | python mail.py $mail_u "Domain $1 will to be expired." "Domain $1 expire date is $e_d." 40 | fi 41 | if [ $t1 -ge $e_t ] && [ $t1 -lt $e_t2 ] 42 | then 43 | python mail.py $mail_u "Domain $1 has been expired" "Domain $1 expire date is $e_d." 44 | fi 45 | } 46 | 47 | #检测上次运行的whois查询进程是否存在 48 | #若存在,需要杀死进程,以免影响本次脚本执行 49 | if pgrep whois &>/dev/null 50 | then 51 | killall -9 whois 52 | fi 53 | 54 | is_install_whois 55 | 56 | for d in aaa.net aaa.com bbb.com aaa.cn ccc.com 57 | do 58 | notify $d & 59 | done 60 | ``` 61 | -------------------------------------------------------------------------------- /codes/11.md: -------------------------------------------------------------------------------- 1 | #### 测试人员名单 2 | ``` 3 | xiaoguisheng 4 | guoyuqing 5 | xiongyongzheng 6 | mengjintang 7 | chaizuzhou 8 | zhousheng 9 | xufangming 10 | zhaoliangyun 11 | hanshiru 12 | wangxianyi 13 | zhangjipei 14 | luxiuli 15 | yangshugen 16 | guoyongzhi 17 | lijianguo 18 | wuqiongchen 19 | dinglin 20 | yaoyashan 21 | yinzijia 22 | wangbencheng 23 | liuxiuwen 24 | chenzuqi 25 | leyuguo 26 | baozongyao 27 | fenghao 28 | sunxiaoquan 29 | zhangyaxian 30 | lijiuzhe 31 | dulichun 32 | lixi 33 | shenpeiwen 34 | zousilin 35 | luoping 36 | chaiyan 37 | fandaozhang 38 | huzixiang 39 | jinzhen 40 | zhujunfeng 41 | liqianbiao 42 | hangyanliang 43 | luorenjian 44 | loujianji 45 | fujianzhou 46 | gengyiwu 47 | jinjigui 48 | liuzhizhong 49 | lisanyan 50 | lisili 51 | zhangyiyu 52 | songguozhen 53 | zhangxinghua 54 | zhaozhiyong 55 | huanghe 56 | xiaojie 57 | fanhongfei 58 | wangguiwen 59 | renshumin 60 | songfuying 61 | zhanghaibo 62 | liguangqun 63 | puaihua 64 | yanzhihua 65 | gaojixian 66 | liulai 67 | funing 68 | chenruizhi 69 | chendaxin 70 | laishaoying 71 | xujian 72 | xiaozhekou 73 | xuxiaping 74 | jiangchunqing 75 | ``` 76 | 77 | #### 参考脚本 78 | ``` 79 | #!/bin/bash 80 | #给人员划分小组 81 | #作者:阿铭 82 | #日期:2018-10-11 83 | #版本:v1.0 84 | 85 | #人员列表文件 86 | f=member.txt 87 | #小组数 88 | group_n=7 89 | #人员总数 90 | member_n=`wc -l $f|awk '{print $1}'` 91 | 92 | #根据姓名计算该用户所在小组的id 93 | get_n() 94 | { 95 | #根据姓名计算cksum值 96 | l=`echo $1|cksum|awk '{print $1}'` 97 | #获取一个随机数 98 | n1=$RANDOM 99 | #cksum值和随机数相加,然后除以小组数取余,这样可以确保每次获取到的余数都不一样 100 | n2=$[$n1+$l] 101 | g_id=$[$n1%$group_n] 102 | #假如小组数为7,则余数范围0-6,如果余数为0,则小组为7 103 | if [ $g_id -eq 0 ] 104 | then 105 | g_id=$group_n 106 | fi 107 | echo $g_id 108 | } 109 | 110 | for i in `seq 1 $group_n` 111 | do 112 | #n_$i.txt为临时文件,用来记录该小组内的成员 113 | #脚本之前执行过,则该文件会存在,本次执行脚本前应该删除掉这个临时文件 114 | [ -f n_$i.txt ] && rm -f n_$i.txt 115 | done 116 | 117 | 118 | shuf $f|while read name 119 | do 120 | #计算用户所在小组的id 121 | g=`get_n $name` 122 | #将人员追加写入到他对应的小组里 123 | echo $name >> n_$g.txt 124 | done 125 | 126 | #定义计算文件行数的函数 127 | nu(){ 128 | wc -l $1|awk '{print $1}' 129 | } 130 | 131 | #获取组员人数最多的小组 132 | max(){ 133 | ma=0 134 | for i in `seq 1 $group_n|shuf` 135 | do 136 | n=`nu n_$i.txt` 137 | if [ $n -gt $ma ] 138 | then 139 | ma=$n 140 | fi 141 | done 142 | echo $ma 143 | } 144 | 145 | #获取组员人数最少的小组 146 | min(){ 147 | mi=$member_n 148 | for i in `seq 1 $group_n|shuf` 149 | do 150 | n=`nu n_$i.txt` 151 | if [ $n -lt $mi ] 152 | then 153 | mi=$n 154 | fi 155 | done 156 | echo $mi 157 | } 158 | 159 | #定义四舍五入函数 160 | div() 161 | { 162 | n=`echo "scale=1;$1/$2"|bc` 163 | n1=`echo "scale=1;$n+0.5"|bc` 164 | echo $n1|cut -d. -f1 165 | } 166 | 167 | #小组组员平均值(非四舍五入) 168 | ava_n=$[$member_n/$group_n] 169 | #小组组员平均值(四舍五入) 170 | ava_n1=`div $member_n $group_n` 171 | 172 | if [ $ava_n -eq $ava_n1 ] 173 | then 174 | #定义初始最小值 175 | ini_min=1 176 | #以下while循环要做的事情,就是要把人数多的组里的人搞到人数少的组里去 177 | #此while循环的条件是,当人数最少的组成员数小于组员平均值 178 | while [ $ini_min -lt $ava_n1 ] 179 | do 180 | #找出人数最多的组 181 | m1=`max` 182 | #找出人数最少的组 183 | m2=`min` 184 | for i in `seq 1 $group_n|shuf` 185 | do 186 | n=`nu n_$i.txt` 187 | #找到人数最多的组对应的文件f1(可能有多个,这里取出现的第一个即可) 188 | if [ $n -eq $m1 ] 189 | then 190 | f1=n_$i.txt 191 | #找到人数最少的组对应的文件f2(可能有多个,这里取出现的第一个即可) 192 | elif [ $n -eq $m2 ] 193 | then 194 | f2=n_$i.txt 195 | fi 196 | done 197 | #取f1中最后一个人名 198 | name=`tail -n1 $f1` 199 | #将这个人名追加写入f2中 200 | echo $name >> $f2 201 | #在f1中删除刚刚取走的人名 202 | sed -i "/$name/d" $f1 203 | #把此时的最少组人员数赋值给ini_min 204 | ini_min=`min` 205 | done 206 | else 207 | #定义初始最大值 208 | ini_max=$member_n 209 | while [ $ini_max -gt $ava_n1 ] 210 | do 211 | #找出人数最多的组 212 | m1=`max` 213 | #找出人数最少的组 214 | m2=`min` 215 | for i in `seq 1 $group_n|shuf` 216 | do 217 | n=`nu n_$i.txt` 218 | #找到人数最多的组对应的文件f1(可能有多个,这里取出现的第一个即可) 219 | if [ $n -eq $m1 ] 220 | then 221 | f1=n_$i.txt 222 | #找到人数最少的组对应的文件f2(可能有多个,这里取出现的第一个即可) 223 | elif [ $n -eq $m2 ] 224 | then 225 | f2=n_$i.txt 226 | fi 227 | done 228 | #取f1中最后一个人名 229 | name=`tail -n1 $f1` 230 | #将这个人名追加写入f2中 231 | echo $name >> $f2 232 | #在f1中删除刚刚取走的人名 233 | sed -i "/$name/d" $f1 234 | #把此时的最少组人员数赋值给ini_min 235 | ini_max=`max` 236 | done 237 | fi 238 | 239 | for i in `seq 1 $group_n` 240 | do 241 | echo -e "\033[34m$i 组成员有:\033[0m" 242 | cat n_$i.txt 243 | #把临时文件删除 244 | rm -f n_$i.txt 245 | echo 246 | done 247 | 248 | ``` 249 | -------------------------------------------------------------------------------- /codes/12.md: -------------------------------------------------------------------------------- 1 | #### shell多线程例子 2 | ``` 3 | #!/bin/bash 4 | #创建命名管道123.fifo文件 5 | mkfifo 123.fifo 6 | #将命名管道123.fifo和文件描述符1000绑定,即fd1000的输入输出都是在123.fifo中 7 | exec 1000<>123.fifo 8 | 9 | #连续向fd1000中写入两次空行 10 | echo >&1000 11 | echo >&1000 12 | 13 | #循环10次 14 | for i in `seq 1 10` 15 | do 16 | #每循环一次,读一次fd1000中的内容,即空行,只有读到空行了,才会执行{ }内的指令 17 | #每次循环都需要打印当前的时间,休眠1秒,然后再次向fd1000中写入空行,这样后续的read就有内容了 18 | #read指令不仅可以赋值,也可以跟一个函数,用{ }括起来,函数中是多条指令 19 | read -u1000 20 | { 21 | date +%T 22 | echo $i 23 | sleep 1 24 | echo >&1000 25 | } & //丢到后台去,这样10次很快就循环完,只不过这些任务是在后台跑着。由于我们一开始就向fd1000里写入了两个空行,所以read会一次性读到两行。 26 | done 27 | #等待所有后台任务执行完成 28 | wait 29 | #删除fd1000 30 | exec 1000>&- 31 | #删除命名管道 32 | rm -f 123.fifo 33 | ``` 34 | 35 | 本案例参考脚本 36 | ``` 37 | #!/bin/bash 38 | #多线程备份数据库 39 | #作者:阿铭 40 | #日期:2018-10-14 41 | #版本:v1.0 42 | 43 | ##假设100个库的库名、host、port以及配置文件路径存到了一个文件里,文件名字为/tmp/databases.list 44 | ##格式:db1 10.10.10.2 3308 /data/mysql/db1/my.cnf 45 | ##备份数据库使用xtrabackup(由于涉及到myisam,命令为inoobackupex) 46 | 47 | exec &> /tmp/mysql_bak.log 48 | 49 | if ! which innobackupex &>/dev/nll 50 | then 51 | echo "安装xtrabackup工具" 52 | rpm -ivh http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm && \ 53 | yum install -y percona-xtrabackup-24 54 | if [ $? -ne 0 ] 55 | then 56 | echo "安装xtrabackup工具出错,请检查。" 57 | exit 1 58 | fi 59 | fi 60 | 61 | bakdir=/data/backup/mysql 62 | bakuser=vyNctM 63 | bakpass=99omeaBHh 64 | 65 | function bak_data { 66 | db_name=$1 67 | db_host=$2 68 | db_port=$3 69 | cnf=$4 70 | [ -d $bakdir/$db_name ] || mkdir -p $bakdir/$db_name 71 | innobackupex --defaults-file=$4 --host=$2 --port=$3 --user=$bakuser --password=$bakpass $bakdir/$1 72 | if [ $? -ne 0 ] 73 | then 74 | echo "备份数据库$1出现问题。" 75 | fi 76 | } 77 | 78 | fifofile=/tmp/$$ 79 | mkfifo $fifofile 80 | exec 1000<>$fifofile 81 | 82 | 83 | thread=10 84 | for ((i=0;i<$thread;i++)) 85 | do 86 | echo >&1000 87 | done 88 | 89 | cat /tmp/databases.list | while read line 90 | do 91 | read -u1000 92 | { 93 | bak_data `echo $line` 94 | echo >&1000 95 | } & 96 | done 97 | 98 | wait 99 | exec 1000>&- 100 | rm -f $fifofile 101 | ``` 102 | -------------------------------------------------------------------------------- /codes/13.md: -------------------------------------------------------------------------------- 1 | #### 本案例参考脚本 2 | ``` 3 | #!/bin/bash 4 | #监控CDN节点 5 | #作者:阿铭 6 | #日期:2018-10-18 7 | 8 | url="http://www.aminglinux.com/test.php" 9 | s_ip="88.88.88.88" 10 | ipf="/data/cdn_ip.list" 11 | mail_user=admin@admin.com 12 | 13 | #检查是否有curl命令 14 | if ! which curl &>/dev/null 15 | then 16 | yum install -y curl 17 | fi 18 | 19 | mycurl() 20 | { 21 | curl --connect-timeout 2 -x$1:80 $url 2>/dev/null 22 | } 23 | 24 | #定义告警函数(这里的mail.py是案例二中那个脚本) 25 | m_mail() { 26 | log=$1 27 | t_s=`date +%s` 28 | t_s2=`date -d "1 hours ago" +%s` 29 | if [ ! -f /tmp/$log ] 30 | then 31 | #创建$log文件 32 | touch /tmp/$log 33 | #增加a权限,只允许追加内容,不允许更改或删除 34 | chattr +a /tmp/$log 35 | #第一次告警,可以直接写入1小时以前的时间戳 36 | echo $t_s2 >> /tmp/$log 37 | fi 38 | #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳 39 | t_s2=`tail -1 /tmp/$log|awk '{print $1}'` 40 | #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳 41 | echo $t_s>>/tmp/$log 42 | #取两次时间戳差值 43 | v=$[$t_s-$t_s2] 44 | #如果差值超过1800,立即发邮件 45 | if [ $v -gt 1800 ] 46 | then 47 | #发邮件,其中$2为mail函数的第二个参数,这里为一个文件 48 | python mail.py $mail_user "节点$1异常" "`cat $2`" 2>/dev/null 49 | #定义计数器临时文件,并写入0 50 | echo "0" > /tmp/$log.count 51 | else 52 | #如果计数器临时文件不存在,需要创建并写入0 53 | if [ ! -f /tmp/$log.count ] 54 | then 55 | echo "0" > /tmp/$log.count 56 | fi 57 | nu=`cat /tmp/$log.count` 58 | #30分钟内每发生1次告警,计数器加1 59 | nu2=$[$nu+1] 60 | echo $nu2>/tmp/$log.count 61 | #当告警次数超过30次,需要再次发邮件 62 | if [ $nu2 -gt 30 ] 63 | then 64 | python mail.py $mail_user "节点$1异常持续30分钟了" "`cat $2`" 2>/dev/null 65 | #第二次告警后,将计数器再次从0开始 66 | echo "0" > /tmp/$log.count 67 | fi 68 | fi 69 | } 70 | 71 | mycurl $s_ip >/tmp/s.html 72 | 73 | for ip in `cat $ipf` 74 | do 75 | mycurl $ip >/tmp/$ip.html 76 | #对比源站的页面和CDN节点的页面是否有差异 77 | diff /tmp/s.html /tmp/$ip.html > /tmp/$ip.diff 2>/dev/null 78 | n=`wc -l /tmp/$ip.diff|awk '{print $1}'` 79 | #如果有差异,那么对比结果行数肯定大于0 80 | if [ $n -gt 0 ] 81 | then 82 | m_mail $ip /tmp/$ip.diff 83 | fi 84 | done 85 | 86 | ``` 87 | 88 | #### 扩展需求脚本 89 | 90 | ``` 91 | #/bin/bash 92 | #监控指定页面是否是非200状态码 93 | #作者:阿铭 94 | #日期:2018-10-18 95 | 96 | url="http://www.test.com/test.html" 97 | mail_user=admin@admin.com 98 | 99 | #检查是否有curl命令 100 | if ! which curl &>/dev/null 101 | then 102 | yum install -y curl 103 | fi 104 | 105 | #定义告警函数(这里的mail.py是案例二中那个脚本) 106 | m_mail() { 107 | log=$1 108 | t_s=`date +%s` 109 | t_s2=`date -d "1 hours ago" +%s` 110 | if [ ! -f /tmp/$log ] 111 | then 112 | #创建$log文件 113 | touch /tmp/$log 114 | #增加a权限,只允许追加内容,不允许更改或删除 115 | chattr +a /tmp/$log 116 | #第一次告警,可以直接写入1小时以前的时间戳 117 | echo $t_s2 >> /tmp/$log 118 | fi 119 | #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳 120 | t_s2=`tail -1 /tmp/$log|awk '{print $1}'` 121 | #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳 122 | echo $t_s>>/tmp/$log 123 | #取两次时间戳差值 124 | v=$[$t_s-$t_s2] 125 | #如果差值超过1800,立即发邮件 126 | if [ $v -gt 1800 ] 127 | then 128 | #发邮件,其中$2为mail函数的第二个参数,这里为一个文件 129 | python mail.py $mail_user "$url访问异常" "`cat $2`" 2>/dev/null 130 | #定义计数器临时文件,并写入0 131 | echo "0" > /tmp/$log.count 132 | else 133 | #如果计数器临时文件不存在,需要创建并写入0 134 | if [ ! -f /tmp/$log.count ] 135 | then 136 | echo "0" > /tmp/$log.count 137 | fi 138 | nu=`cat /tmp/$log.count` 139 | #30分钟内每发生1次告警,计数器加1 140 | nu2=$[$nu+1] 141 | echo $nu2>/tmp/$log.count 142 | #当告警次数超过30次,需要再次发邮件 143 | if [ $nu2 -gt 30 ] 144 | then 145 | python mail.py $mail_user "$url访问异常持续30分钟了" "`cat $2`" 2>/dev/null 146 | #第二次告警后,将计数器再次从0开始 147 | echo "0" > /tmp/$log.count 148 | fi 149 | fi 150 | } 151 | 152 | curl -I $url &>/tmp/curl.txt 153 | code=`grep '^HTTP/1.1' /tmp/curl.txt|awk '{print $2}'` 154 | if [ -z "$code" ] || [ $code -ne 200 ] 155 | then 156 | m_mail webcode /tmp/curl.txt 157 | fi 158 | ``` 159 | -------------------------------------------------------------------------------- /codes/14.md: -------------------------------------------------------------------------------- 1 | #### 本案例参考脚本 2 | ``` 3 | #!/bin/bash 4 | #本脚本的功能是在LAMP环境中增加站点,包括apache配置、FTP增加用户、MySQL增加库和用户 5 | #作者:阿铭 6 | #日期:2018-10-24 7 | 8 | #网站目录 9 | webdir=/data/wwwroot 10 | 11 | #ftp的虚拟用户配置文件目录 12 | ftpudir=/etc/vsftpd/vuuser 13 | 14 | #ftp虚拟用户密码文件 15 | ftpuserfile=/root/login 16 | 17 | #mysql命令行登录root 18 | mysqlc="/usr/local/mysql/bin/mysql -uroot -pjk1hYUcnt6" 19 | 20 | #apache虚拟主机配置文件 21 | httpd_config_f="/usr/local/apache2/conf/extra/httpd-vhosts.conf" 22 | 23 | #定义增加MySQL库和用户的函数 24 | add_mysql_user() 25 | { 26 | #生成随机密码 27 | mysql_p=`mkpasswd -s 0 -l 12` 28 | 29 | #将密码保存到临时文件里,这里的$pro为用户自定义的项目名字 30 | echo "$pro $mysql_p" >/tmp/$pro.txt 31 | 32 | #这里使用嵌入文档的形式(需顶格),将创建用户并授权的命令传递给mysql 33 | $mysqlc <> $ftpuserfile 45 | echo "$ftp_p" >> $ftpuserfile 46 | 47 | #将用户、密码文件转换为密码db文件 48 | db_load -T -t hash -f $ftpuserfile /etc/vsftpd/vsftpd_login.db 49 | cd $ftpudir 50 | 51 | #这里的aaa是一个文件,是之前的一个项目,可以作为配置模板 52 | cp aaa $pro 53 | 54 | #把里面的aaa改为新的项目名字 55 | sed -i "s/aaa/$pro/" $pro 56 | 57 | #重启vsftpd服务 58 | /etc/init.d/vsftpd restart 59 | } 60 | 61 | #定义增加apache虚拟主机的函数 62 | config_httpd() 63 | { 64 | #增加网站根目录,和域名保持一致,这里的$dom为用户自定义的域名 65 | mkdir $webdir/$dom 66 | 67 | #将网站根目录属主和属组设置为ftp用户 68 | chown vsftpd:vsftpd $webdir/$dom 69 | 70 | #用嵌入文档(需顶格),把虚拟主机配置写入到配置文件里 71 | cat >> $httpd_config_f < 73 | DocumentRoot $webdir/$dom 74 | ServerName $dom 75 | 76 | AllowOverride none 77 | Require all granted 78 | 79 | 80 | EOF 81 | 82 | #重载apache服务 83 | /usr/local/apache2/bin/apachectl graceful 84 | } 85 | 86 | read -p "input the project name: " pro 87 | read -p "input the domain: " dom 88 | 89 | add_mysql_user 90 | add_ftp_user 91 | config_httpd 92 | ``` 93 | -------------------------------------------------------------------------------- /codes/15.md: -------------------------------------------------------------------------------- 1 | #### 截取两个关键词中间的行 2 | 3 | ##### 测试文本1.txt 4 | ``` 5 | alskdfkjlasldkjfabalskdjflkajsd 6 | asldkfjjk232k3jlk2 7 | alskk2lklkkabclaksdj 8 | skjjfk23kjalf09wlkjlah lkaswlekjl9 9 | aksjdf 10 | 123asd232323 11 | aaaaaaaaaa 12 | 222222222222222222 13 | abcabc12121212 14 | fa2klj 15 | slkj32k3j 16 | 22233232123 17 | bbbbbbb 18 | ddddddddddd 19 | ``` 20 | 21 | ##### 脚本内容 22 | ``` 23 | #!/bin/bash 24 | #先获取abc和123所在行的行号 25 | egrep -n 'abc|123' 1.txt |awk -F ':' '{print $1}' > /tmp/line_number.txt 26 | 27 | #计算一共有多少包含abc和123的行 28 | n=`wc -l /tmp/line_number.txt|awk '{print $1}'` 29 | 30 | #计算一共有多少对abc和123 31 | n2=$[$n/2] 32 | 33 | for i in `seq 1 $n2` 34 | do 35 | #每次循环都要处理两行,第一次是1,2,第二次是3,4,依此类推 36 | m1=$[$i*2-1] 37 | m2=$[$i*2] 38 | 39 | #每次遍历都要获取abc和123的行号 40 | nu1=`sed -n "$m1"p /tmp/line_number.txt` 41 | nu2=`sed -n "$m2"p /tmp/line_number.txt` 42 | 43 | #获取abc下面一行的行号 44 | nu3=$[$nu1+1] 45 | 46 | #获取123上面一行的行号 47 | nu4=$[$nu2-1] 48 | 49 | #用sed把abc和123中间的行打印出来 50 | sed -n "$nu3,$nu4"p 1.txt 51 | 52 | #便于分辨,添加分隔行符号 53 | echo "=============" 54 | done 55 | ``` 56 | 57 | #### 本案例参考脚本 58 | ``` 59 | #!/bin/bash 60 | #按要求输出XML内容,本脚本定制性较强,不可通用 61 | #作者:阿铭 62 | #日期:2018-10-26 63 | 64 | #假设要处理的XML文档名字为test.xml 65 | #获取所在的行号 66 | grep -n 'artifactItem>' test.xml |awk '{print $1}' |sed 's/://' > /tmp/line_number.txt 67 | 68 | #计算的行一共有多少行 69 | n=`wc -l /tmp/line_number.txt|awk '{print $1}'` 70 | 71 | #定义获取关键词和其值的函数 72 | get_value(){ 73 | #$1和$2为函数的两个参数,即下一行和上一行的行号(这个操作在下面) 74 | #截取出中间的内容,然后获取关键词(如groupId)和其对应的值,写入/tmp/value.txt 75 | sed -n "$1,$2"p test.xml|awk -F '<' '{print $2}'|awk -F '>' '{print $1,$2}' > /tmp/value.txt 76 | 77 | #遍历整个/tmp/value.txt文档 78 | cat /tmp/value.txt|while read line 79 | do 80 | #x为关键词,如groupId 81 | #y为关键词的值 82 | x=`echo $line|awk '{print $1}'` 83 | y=`echo $line|awk '{print $2}'` 84 | echo artifactItem:$x:$y 85 | done 86 | } 87 | 88 | #由于/tmp/line_number.txt是成对出现的,n2为一共多少对 89 | n2=$[$n/2] 90 | 91 | #针对每一对,打印关键词和对应的值 92 | for j in `seq 1 $n2` 93 | do 94 | #每次循环都要处理两行,第一次是1,2,第二次是3,4,依此类推 95 | m1=$[$j*2-1] 96 | m2=$[$j*2] 97 | 98 | #每次遍历都要获取的行号 99 | nu1=`sed -n "$m1"p /tmp/line_number.txt` 100 | nu2=`sed -n "$m2"p /tmp/line_number.txt` 101 | 102 | #获取下面一行的行号 103 | nu3=$[$nu1+1] 104 | 105 | #获取上面一行的行号 106 | nu4=$[$nu2-1] 107 | 108 | get_value $nu3 $nu4 109 | done 110 | ``` 111 | -------------------------------------------------------------------------------- /codes/16.md: -------------------------------------------------------------------------------- 1 | #### expect脚本登录机器 2 | ``` 3 | #!/usr/bin/expect 4 | #定义变量 5 | set passwd "123abc321" 6 | #执行命令 7 | spawn ssh root@192.168.10.11 8 | #与远程机器交互 截取特定信息 发送变量 9 | expect { 10 | "yes/no" { send "yes\r";exp_continue } 11 | "password:" { send "$passwd\r" } 12 | } 13 | interact 14 | ``` 15 | #### expect脚本登录远程机器并执行命令 16 | ``` 17 | #!/usr/bin/expect 18 | set host "192.168.80.102" 19 | set passwd "aaa123bbb" 20 | spawn ssh user1@$host 21 | expect { 22 | "yes/no" {send "yes\r";exp_continue} 23 | "password:" {send "$passwd\r"} 24 | } 25 | expect "]*" 26 | send "touch /tmp/test.aa\r" 27 | expect "]*" 28 | send "echo 111 >/tmp/test.aa\r" 29 | expect "]*" 30 | send "exit\r" 31 | ``` 32 | #### 给expect脚本传递参数 33 | ``` 34 | #!/usr/bin/expect 35 | set host [lindex $argv 0] 36 | set passwd [lindex $argv 1] 37 | spawn ssh root@$host 38 | expect { 39 | "yes/no" {send "yes\r"} 40 | "password:" {send "$passwd\r"} 41 | } 42 | interact 43 | ``` 44 | #### 本案例参考脚本 45 | ``` 46 | #!/bin/bash 47 | #批量关闭远程机器上的Tomcat服务 48 | #作者:阿铭 49 | #日期:2018-10-29 50 | 51 | ipfile=/data/ip-passwd.txt 52 | 53 | cat >> kill_tomcat.exp </dev/null 11 | then 12 | yum install -y sysstat 13 | #如果你的机器为ubuntu,请使用这个命令:apt-get install -y sysstat 14 | fi 15 | 16 | #判断机器上是否安装iotop命令 17 | if ! which iotop &>/dev/null 18 | then 19 | yum install -y iotop 20 | #如果你的机器为ubuntu,请使用这个命令:apt-get install -y iotop 21 | fi 22 | 23 | #定义记录日志的目录 24 | logdir=/tmp/iolog 25 | [ -d $logdir ] || mkdir $logdir 26 | 27 | #定义日志名字 28 | dt=`date +%F` 29 | 30 | #定义获取io的函数(取5次平均值) 31 | get_io() 32 | { 33 | iostat -dx 1 5 > $logdir/iostat.log 34 | sum=0 35 | 36 | #取最后一列的%util值循环遍历然后相加 37 | for ut in `grep "^$1" $logdir/iostat.log|awk '{print $NF}'|cut -d. -f1` 38 | do 39 | sum=$[$sum+$ut] 40 | done 41 | echo $[$sum/5] 42 | } 43 | 44 | #这里的true表示条件为真 45 | while true 46 | do 47 | #获取所有设备,对所有设备名遍历 48 | for d in `iostat -dx|egrep -v '^$|Device:|CPU\)'|awk '{print $1}'` 49 | do 50 | io=`get_io $d` 51 | #如果io使用率大于等于80 52 | if [ $io -ge 80 ] 53 | then 54 | #向日志里记录时间、iostat和iotop信息 55 | date >> $logdir/$dt 56 | cat $logdir/iostat.log >>$logdir/$dt 57 | iotop -obn2 >>$logdir/$dt 58 | echo "####################" >>$logdir/$dt 59 | fi 60 | #休眠10秒,继续以上步骤 61 | done 62 | sleep 10 63 | done 64 | ``` 65 | -------------------------------------------------------------------------------- /codes/19.md: -------------------------------------------------------------------------------- 1 | #### 日志片段 2 | ``` 3 | Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start 4 | INFO: Starting ProtocolHandler ["http-bio-8080"] 5 | Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start 6 | INFO: Starting ProtocolHandler ["ajp-bio-8009"] 7 | Oct 29, 2018 01:52:24 PM org.apache.catalina.startup.Catalina start 8 | INFO: Server startup in 2102 ms 9 | ``` 10 | #### 启动脚本 11 | ``` 12 | #!/bin/bash 13 | export CATALINA_HOME=/usr/local/tomcat 14 | export CATALINA_BASE=/data/tomcat-instance/www.123.com 15 | TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'` 16 | if [ -n "$TOMCAT_ID" ] 17 | then 18 | echo "tomcat(${TOMCAT_ID}) still running now , please shutdown it first"; 19 | exit 2; 20 | else 21 | $CATALINA_HOME/bin/startup.sh 22 | if [ "$?" = "0" ]; then 23 | echo "start succeed" 24 | else 25 | echo "sart failed" 26 | fi 27 | fi 28 | ``` 29 | #### 关闭脚本 30 | ``` 31 | #!/bin/bash 32 | export CATALINA_HOME=/usr/local/tomcat 33 | export CATALINA_BASE=/data/tomcat-instance/www.123.com 34 | TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'` 35 | if [ -n "$TOMCAT_ID" ] ; then 36 | TOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh` 37 | if [ "$?" = "0" ]; then 38 | echo "stop succeed" 39 | else 40 | echo "stop failed" 41 | fi 42 | else 43 | echo "Tomcat instance not found" 44 | exit 45 | fi 46 | ``` 47 | 48 | #### 本案例参考脚本 49 | ``` 50 | #!/bin/bash 51 | #截取指定Tomcat的日志片段 52 | #作者:阿铭 53 | #日期:2018-11-08 54 | 55 | LANG=en 56 | logfile="/opt/TOM/$1/logs/catalina.out" 57 | 58 | #将当天的英文月、数字日期、数字年作为变量赋值给d_mdy 59 | d_mdy=`date "+%b %d, %Y"` 60 | 61 | #判断参数个数 62 | if [ $# -ne 2 ] && [ $# -ne 3 ] 63 | then 64 | echo "你提供的参数个数不对,请提供2个或者3个参数。例:sh $0 t1 08:01:00 14:00:00" 65 | exit 1 66 | fi 67 | 68 | #判断第一个参数是否符合要求 69 | if ! echo $1|grep -qE '^t1$|^t2$|^t3$|^t4$' 70 | then 71 | echo "第一个参数必须是t1、t2、t3或t4" 72 | exit 1 73 | fi 74 | 75 | #判断时间有效性 76 | judge_time() 77 | { 78 | date -d "$1" +%s &>/dev/null 79 | if [ $? -ne 0 ] 80 | then 81 | echo "你提供的时间$1格式不正确" 82 | exit 1 83 | fi 84 | } 85 | 86 | #判断提供的时间点是否在日志中出现 87 | judge_time_in_log() 88 | { 89 | if ! grep -q "$d_mdy $(tr_24_12 $1)" $logfile 90 | then 91 | echo "你提供的时间$1在日志$logfile中不曾出现,请换一个时间点" 92 | exit 1 93 | fi 94 | } 95 | 96 | #将24小时制时间转换为12小时 97 | tr_24_12() 98 | { 99 | date -d "$1" +%r 100 | } 101 | 102 | #判断第2个参数是否合法 103 | judge_time $2 104 | 105 | #判断起始时间点是否出现在日志里 106 | judge_time_in_log $2 107 | 108 | #如果提供第3个参数 109 | if [ $# -eq 3 ] 110 | then 111 | #判断第3个参数是否合法 112 | judge_time $3 113 | 114 | #判断起始时间是否早于结束时间 115 | t1=`date -d "$2" +%s` 116 | t2=`date -d "$3" +%s` 117 | if [ $t2 -lt $t1 ] 118 | then 119 | echo "你提供的时间$2比$3要晚,应该把早的时间放到前面" 120 | exit 121 | fi 122 | 123 | #判断提供的结束时间点是否出现在日志中 124 | judge_time_in_log $3 125 | fi 126 | 127 | 128 | #取起始时间所在行行号 129 | begin_n=`grep -n "$d_mdy $(tr_24_12 $2)" $logfile|head -1|awk -F ':' '{print $1}'` 130 | 131 | #取结束时间所在行行号,并用sed截取日志内容 132 | if [ $# -eq 3 ] 133 | then 134 | n=`grep -n "$d_mdy $(tr_24_12 $3)" $logfile|tail -1|awk -F ':' '{print $1}'` 135 | #结束日期所在行的下一行才是日志的内容 136 | end_n=$[$n+1] 137 | sed -n "$begin_n,$end_n"p $logfile 138 | else 139 | sed -n "$begin_n,$"p $logfile 140 | fi 141 | ``` 142 | -------------------------------------------------------------------------------- /codes/2.md: -------------------------------------------------------------------------------- 1 | #### 邮件脚本mail.py(注意,python2.6/2.7版本没问题,python3有问题) 2 | ``` 3 | #!/usr/bin/python 4 | #coding:utf-8 5 | import smtplib 6 | from email.mime.text import MIMEText 7 | import sys 8 | mail_host = 'smtp.163.com' 9 | mail_user = 'test@163.com' 10 | mail_pass = 'your_mail_password' 11 | mail_postfix = '163.com' 12 | def send_mail(to_list,subject,content): 13 | me = "zabbix 监控告警平台"+"<"+mail_user+"@"+mail_postfix+">" 14 | msg = MIMEText(content, 'plain', 'utf-8') 15 | msg['Subject'] = subject 16 | msg['From'] = me 17 | msg['to'] = to_list 18 | try: 19 | s = smtplib.SMTP() 20 | s.connect(mail_host) 21 | s.login(mail_user,mail_pass) 22 | s.sendmail(me,to_list,msg.as_string()) 23 | s.close() 24 | return True 25 | except Exception,e: 26 | print str(e) 27 | return False 28 | if __name__ == "__main__": 29 | send_mail(sys.argv[1], sys.argv[2], sys.argv[3]) 30 | ``` 31 | 32 | #### 参考脚本 33 | ``` 34 | #!/bin/bash 35 | ##该脚本用来监控网站的502问题 36 | ##作者:阿铭 37 | ##日期:2018-09-16 38 | ##版本:v0.1 39 | 40 | t=`date -d "-1 min" +"%Y:%H:%M:[0-5][0-9]"` 41 | log="/data/logs/access.log" 42 | #假设mail.py已经写好,并放在/usr/local/sbin/下 43 | mail_script="/usr/local/sbin/mail.py" 44 | mail_user=aming@aminglinux.com 45 | 46 | n=`grep $t $log|grep -n " 502 "` 47 | if [ $n -gt 50 ] 48 | then 49 | python $mail_script $mail_user "网站有502" "1分钟内出现了$n次" 50 | fi 51 | ``` 52 | -------------------------------------------------------------------------------- /codes/20.md: -------------------------------------------------------------------------------- 1 | #### expect同步文件 2 | ``` 3 | #!/usr/bin/expect 4 | set passwd "SGs2ox6uj" 5 | set host "192.168.1.180" 6 | spawn rsync -a user01@$host:/tmp/test.txt /tmp/ 7 | expect { 8 | "yes/no" {send "yes\r"} 9 | "password:" {send "$passwd\r"} 10 | } 11 | expect eof 12 | 13 | ``` 14 | #### 传递参数 15 | ``` 16 | #!/usr/bin/expect 17 | set passwd "SGs2ox6uj" 18 | set host [lindex $argv 0] 19 | set file [lindex $argv 1] 20 | spawn rsync -a --files-from=$file / user01@$host:/ 21 | expect { 22 | "yes/no" {send "yes\r"} 23 | "password:" {send "$passwd\r"} 24 | } 25 | expect eof 26 | ``` 27 | #### 本案例参考脚本 28 | ``` 29 | #/bin/bash 30 | ##代码上线 31 | ##作者:阿铭 32 | ##日期:2018-11-12 33 | 34 | #提醒用户,是否更新了要上线的代码列表文件 35 | read -p "你是否已经更新了文件列表./file.list?确认请输入y或者Y,否则按其他任意键退出脚本。" c 36 | 37 | #如果直接按回车,也会退出脚本 38 | if [ -z "$c" ] 39 | then 40 | exit 1 41 | fi 42 | 43 | if [ $c == "y" -o $c == "Y" ] 44 | then 45 | echo "脚本将在2秒后,继续执行。" 46 | #每秒输出一个.共输出两个. 47 | for i in 1 2 48 | do 49 | echo -n "." 50 | sleep 1 51 | done 52 | echo 53 | else 54 | exit 1 55 | fi 56 | 57 | #判断有无./rsync.exp文件 58 | [ -f ./rsync.exp ] && rm -f ./rsync.exp 59 | 60 | #定义rsync.exp 61 | cat >./rsync.exp </dev/null 12 | then 13 | echo "没有mkpasswd命令,安装该命令:" 14 | yum install -y expect 15 | fi 16 | 17 | #判断/data/user_passwd文件是否已经存在 18 | #若存在,应该先删除掉 19 | [ -f /data/user_passwd ] && rm -f /data/user_passwd 20 | 21 | #因为100为三位数,所以只能遍历到99 22 | for n in `seq -w 1 99` 23 | do 24 | pass=`mkpasswd -l 12 -s 0` 25 | echo "添加用户user_$n" 26 | useradd -g users user_$n 27 | echo "给用户user_$n设定密码" 28 | echo $pass |passwd --stdin user_$n 29 | echo "user_$n $pass" >>/data/user_passwd 30 | done 31 | 32 | pass=`mkpasswd -l 12 -s 0` 33 | echo "添加用户user_100" 34 | useradd -g users user_100 35 | echo "给用户user100设定密码" 36 | echo $pass|passwd --stdin user_100 37 | echo "user_100 $pass" >>/data/user_passwd 38 | ``` 39 | -------------------------------------------------------------------------------- /codes/4.md: -------------------------------------------------------------------------------- 1 | #### 参考日志 2 | ``` 3 | 180.98.113.151 - [19/Sep/2018:09:30:07 +0800] "/uc_server/avatar.php?uid=1145811&size=middle" 301 "GET HTTP/1.1" "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13D15 MAGAPPX|4.1.2-4.1.0-41|iPhone OS 9.2.1 iPhone 6|wenyou|C6C25422-279C-4337-8E10-F588D577B9D7|da97ede5be797f79b96d6761bf858632|426ef86c3fc2359dc90468f7bdd0f5e9|c64f2225ec641231cd612bbe08f2b40d" 4 | 61.227.224.229 - [19/Sep/2018:09:30:07 +0800] "/misc.php?mod=ranklist&type=member&view=post" 200 "GET HTTP/1.1" "http://www.wenyou.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0" 5 | 183.207.95.145 [19/Sep/2018:09:30:07 +0800] "/uc_server/avatar.php?uid=1323875&size=middle" 301 "GET HTTP/1.1" "http://app.yikaidai.com/mag/circle/v1/forum/threadViewPage?tid=3446714&circle_id=&themecolor=1aadfa" "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0_3 like Mac OS X) AppleWebKit/604.1.38 " 6 | 114.230.251.50 - [19/Sep/2018:09:30:07 +0800] "/core/attachment/attachment/img?url=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg" 302 "GET HTTP/1.1" "https://app.yikai.com/mag/info/v1/info/infoView?id=55855&themecolor=1aadfa" "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) " 7 | 61.227.224.229 - [19/Sep/2018:09:30:07 +0800] "/misc.php?mod=ranklist&type=member&view=onlinetime" 200 "GET HTTP/1.1" "http://www.wenyou.com/" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0" 8 | ``` 9 | #### 参考脚本 10 | ``` 11 | #! /bin/bash 12 | ## 把访问量比较大的IP封掉,如果20分钟内被封的IP没有请求或者请求很少,需要解封 13 | ## 作者:阿铭 14 | ## 日期:2018-09-20 15 | ## 版本:v0.1 16 | 17 | #定义1分钟以前的时间,用于过滤1分钟以前的日志 18 | t1=`date -d "-1 min" +%Y:%H:%M` 19 | log=/data/logs/access_log 20 | 21 | block_ip() 22 | { 23 | egrep "$t1:[0-5]+" $log > /tmp/tmp_last_min.log 24 | 25 | #把1分钟内访问量高于100的ip记录到一个临时文件中 26 | awk '{print $1}' /tmp/tmp_last_min.log |sort -n |uniq -c|sort -n |awk '$1>100 {print $2}' > /tmp/bad_ip.list 27 | 28 | #计算ip的数量 29 | n=`wc -l /tmp/bad_ip.list|awk '{print $1}'` 30 | 31 | #当ip数大于0时,才会用iptables封掉它 32 | if [ $n -ne 0 ] 33 | then 34 | for ip in `cat /tmp/bad_ip.list` 35 | do 36 | iptables -I INPUT -s $ip -j REJECT 37 | done 38 | #将这些被封的IP记录到日志里 39 | echo "`date` 封掉的IP有:" >> /tmp/block_ip.log 40 | cat /tmp/bad_ip.list >> /tmp/block_ip.log 41 | fi 42 | } 43 | 44 | unblock_ip() 45 | { 46 | #首先将包个数小于5的ip记录到一个临时文件里,把它们标记为白名单IP 47 | iptables -nvL INPUT|sed '1d' |awk '$1<5 {print $8}' > /tmp/good_ip.list 48 | n=`wc -l /tmp/good_ip.list|awk '{print $1}'` 49 | if [ $n -ne 0 ] 50 | then 51 | for ip in `cat /tmp/good_ip.list` 52 | do 53 | iptables -D INPUT -s $ip -j REJECT 54 | done 55 | echo "`date` 解封的IP有:" >> /tmp/unblock_ip.log 56 | cat /tmp/good_ip.list >> /tmp/unblock_ip.log 57 | fi 58 | #当解封完白名单IP后,将计数器清零,进入下一个计数周期 59 | iptables -Z 60 | } 61 | 62 | #取当前时间的分钟数 63 | t=`date +%M` 64 | 65 | #当分钟数为00或者30时(即每隔30分钟),执行解封IP的函数,其他时间只执行封IP的函数 66 | if [ $t == "00" ] || [ $t == "30" ] 67 | then 68 | unblock_ip 69 | block_ip 70 | else 71 | block_ip 72 | fi 73 | ``` 74 | -------------------------------------------------------------------------------- /codes/5.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | ##监控磁盘使用情况,并做告警收敛(30分钟发一次邮件) 5 | ##作者:阿铭 6 | ##日期:2018-09-25 7 | ##版本:v0.1 8 | 9 | #把脚本名字存入变量s_name 10 | s_name=`echo $0|awk -F '/' '{print $NF}'` 11 | #定义收件人邮箱 12 | mail_user=admin@admin.com 13 | 14 | #定义检查磁盘空间使用率函数 15 | chk_sp() 16 | { 17 | 18 | df -m|sed '1d' |awk -F '%| +' '$5>90 {print $7,$5}'>/tmp/chk_sp.log 19 | n=`wc -l /tmp/chk_sp.log|awk '{print $1}'` 20 | if [ $n -gt 0 ] 21 | then 22 | tag=1 23 | for d in `awk '{print $1}' /tmp/chk_sp.log` 24 | do 25 | find $d -type d |sed '1d'|xargs du -sm |sort -nr |head -3 26 | done > /tmp/most_sp.txt 27 | fi 28 | } 29 | 30 | #定义检查inode使用率函数 31 | chk_in() 32 | { 33 | df -i|sed '1d'|awk -F '%| +' '$5>90 {print $7,$5}'>/tmp/chk_in.log 34 | n=`wc -l /tmp/chk_in.log|awk '{print $1}'` 35 | if [ $n -gt 0 ] 36 | then 37 | tag=2 38 | fi 39 | } 40 | 41 | #定义告警函数(这里的mail.py是案例二中那个脚本) 42 | m_mail() { 43 | log=$1 44 | t_s=`date +%s` 45 | t_s2=`date -d "1 hours ago" +%s` 46 | if [ ! -f /tmp/$log ] 47 | then 48 | #创建$log文件 49 | touch /tmp/$log 50 | #增加a权限,只允许追加内容,不允许更改或删除 51 | chattr +a /tmp/$log 52 | #第一次告警,可以直接写入1小时以前的时间戳 53 | echo $t_s2 >> /tmp/$log 54 | fi 55 | #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳 56 | t_s2=`tail -1 /tmp/$log|awk '{print $1}'` 57 | #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳 58 | echo $t_s>>/tmp/$log 59 | #取两次时间戳差值 60 | v=$[$t_s-$t_s2] 61 | #如果差值超过1800,立即发邮件 62 | if [ $v -gt 1800 ] 63 | then 64 | #发邮件,其中$2为mail函数的第二个参数,这里为一个文件 65 | python mail.py $mail_user "磁盘使用率超过90%" "`cat $2`" 2>/dev/null 66 | #定义计数器临时文件,并写入0 67 | echo "0" > /tmp/$log.count 68 | else 69 | #如果计数器临时文件不存在,需要创建并写入0 70 | if [ ! -f /tmp/$log.count ] 71 | then 72 | echo "0" > /tmp/$log.count 73 | fi 74 | nu=`cat /tmp/$log.count` 75 | #30分钟内每发生1次告警,计数器加1 76 | nu2=$[$nu+1] 77 | echo $nu2>/tmp/$log.count 78 | #当告警次数超过30次,需要再次发邮件 79 | if [ $nu2 -gt 30 ] 80 | then 81 | python mail.py $mail_user "磁盘使用率超过90%持续30分钟了" "`cat $2`" 2>/dev/null 82 | #第二次告警后,将计数器再次从0开始 83 | echo "0" > /tmp/$log.count 84 | fi 85 | fi 86 | } 87 | 88 | #把进程情况存入临时文件,如果加管道求行数会有问题 89 | ps aux |grep "$s_name" |grep -vE "$$|grep">/tmp/ps.tmp 90 | p_n=`wc -l /tmp/ps.tmp|awk '{print $1}'` 91 | 92 | #当进程数大于0,则说明上次的脚本还未执行完 93 | if [ $p_n -gt 0 ] 94 | then 95 | exit 96 | fi 97 | 98 | chk_sp 99 | chk_in 100 | 101 | if [ $tag == 1 ] 102 | then 103 | m_mail chk_sp /tmp/most_sp.txt 104 | elif [ $tag == 2 ] 105 | then 106 | m_mail chk_in /tmp/chk_in.log 107 | fi 108 | ``` 109 | -------------------------------------------------------------------------------- /codes/6.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | ##对比两台机器上的文件差异 5 | ##作者:阿铭 6 | ##日期:2018-09-27 7 | ##版本:v0.2 8 | 9 | #假设B机器IP为192.168.0.110 10 | B_ip=192.168.0.110 11 | dir=/data/wwwroot/www.abc.com 12 | #首先检查/tmp/md5.list文件是否存在,存在的话就删除掉,避免影响后续操作 13 | [ -f /tmp/md5.list ] && rm -f /tmp/md5.list 14 | 15 | #把除了uploads以及tmp目录外其他目录下的全部文件列出来 16 | cd $dir 17 | find . \( -path "./uploads*" -o -path "./tmp*" \) -prune -o -type f > /tmp/file.list 18 | 19 | #用while循环,求出所有文件的md5值,并写入一个文件里 20 | cat /tmp/file.list|while read line 21 | do 22 | md5sum $line 23 | done > /tmp/md5.list 24 | 25 | #将md5.list拷贝到B机器 26 | scp /tmp/md5.list $B_ip:/tmp/ 27 | 28 | #判断/tmp/check_md5.sh文件是否存在 29 | [ -f /tmp/check_md5.sh ] && rm -f /tmp/check_md5.sh 30 | 31 | #用Here Document编写check_md5.sh脚本内容 32 | cat >/tmp/check_md5.sh << EOF 33 | #!/bin/bash 34 | dir=/data/wwwroot/www.abc.com 35 | ##注意,这里涉及到的特殊符号都需要脱义,比如反引号和$ 36 | cd \$dir 37 | n=\`wc -l /tmp/md5.list|awk '{print \$1}'\` 38 | for i in \`seq 1 \$n\` 39 | do 40 | file_name=\`sed -n "\$i"p /tmp/md5.list |awk '{print \$2}'\` 41 | md5=\`sed -n "\$i"p /tmp/md5.list|awk '{print \$1}'\` 42 | if [ -f \$file_name ] 43 | then 44 | md5_b=\`md5sum \$file_name|awk '{print \$1}'\` 45 | if [\$md5_b != \$md5 ] 46 | then 47 | echo "\$file_name changed." 48 | fi 49 | else 50 | echo "\$file_name lose." 51 | fi 52 | done > /data/change.log 53 | EOF 54 | scp /tmp/check_md5.sh $B_ip:/tmp/ 55 | ssh $B_ip "/bin/bash /tmp/check_md5.sh" 56 | ``` 57 | -------------------------------------------------------------------------------- /codes/7.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | #检测MySQL主从是否同步 5 | #作者:阿铭 6 | #日期:2018-09-29 7 | #版本:v0.2 8 | 9 | #把脚本名字存入变量s_name 10 | s_name=`echo $0|awk -F '/' '{print $NF}'` 11 | Mysql_c="mysql -uroot -ptpH40Kznv" 12 | mail_user=aming_test@163.com 13 | 14 | #该函数实现邮件告警收敛,在案例五种出现过,通用 15 | m_mail() { 16 | log=$1 17 | t_s=`date +%s` 18 | t_s2=`date -d "1 hours ago" +%s` 19 | if [ ! -f /tmp/$log ] 20 | then 21 | #创建$log文件 22 | touch /tmp/$log 23 | #增加a权限,只允许追加内容,不允许更改或删除 24 | chattr +a /tmp/$log 25 | #第一次告警,可以直接写入1小时以前的时间戳 26 | echo $t_s2 >> /tmp/$log 27 | fi 28 | #无论$log文件是否是刚刚创建,都需要查看最后一行的时间戳 29 | t_s2=`tail -1 /tmp/$log|awk '{print $1}'` 30 | #取出最后一行即上次告警的时间戳后,立即写入当前的时间戳 31 | echo $t_s>>/tmp/$log 32 | #取两次时间戳差值 33 | v=$[$t_s-$t_s2] 34 | #如果差值超过1800,立即发邮件 35 | if [ $v -gt 1800 ] 36 | then 37 | #发邮件,其中$2为mail函数的第二个参数,这里为一个文件 38 | python mail.py $mail_user $1 "`cat $2`" 2>/dev/null 39 | #定义计数器临时文件,并写入0 40 | echo "0" > /tmp/$log.count 41 | else 42 | #如果计数器临时文件不存在,需要创建并写入0 43 | if [ ! -f /tmp/$log.count ] 44 | then 45 | echo "0" > /tmp/$log.count 46 | fi 47 | nu=`cat /tmp/$log.count` 48 | #30分钟内每发生1次告警,计数器加1 49 | nu2=$[$nu+1] 50 | echo $nu2>/tmp/$log.count 51 | #当告警次数超过30次,需要再次发邮件 52 | if [ $nu2 -gt 30 ] 53 | then 54 | python mail.py $mail_user "$1 30 min" "`cat $2`" 2>/dev/null 55 | #第二次告警后,将计数器再次从0开始 56 | echo "0" > /tmp/$log.count 57 | fi 58 | fi 59 | } 60 | 61 | #把进程情况存入临时文件,如果加管道求行数会有问题 62 | ps aux |grep "$s_name" |grep -vE "$$|grep">/tmp/ps.tmp 63 | p_n=`wc -l /tmp/ps.tmp|awk '{print $1}'` 64 | 65 | #当进程数大于0,则说明上次的脚本还未执行完 66 | if [ $p_n -gt 0 ] 67 | then 68 | exit 69 | fi 70 | 71 | #先执行一条执行show processlist,看是否执行成功 72 | $Mysql_c -e "show processlist" >/tmp/mysql_pro.log 2>/tmp/mysql_log.err 73 | 74 | #如果上一条命令执行不成功,说明这个MySQL服务出现了问题 75 | if [ $? -gt 0 ] 76 | then 77 | m_mail mysql_service_error /tmp/mysql_log.err 78 | exit 79 | else 80 | $Mysql_c -e "show slave status\G" >/tmp/mysql_s.log 81 | n1=`wc -l /tmp/mysql_s.log|awk '{print $1}'` 82 | 83 | if [ $n1 -gt 0 ] 84 | then 85 | y1=`grep 'Slave_IO_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'` 86 | y2=`grep 'Slave_SQL_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'` 87 | 88 | if [ $y1 == "No" ] || [ $y2 == "No" ] 89 | then 90 | m_mail mysql_slavestatus_error /tmp/mysql_s.log 91 | fi 92 | fi 93 | fi 94 | ``` 95 | -------------------------------------------------------------------------------- /codes/8.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | #这是一个傻瓜运维脚本,根据列表输入对应数字即可实现想要功能 5 | #作者:阿铭 6 | #日期:2018-10-04 7 | #版本:v0.1 8 | 9 | LANG=en 10 | sar 1 5 > /tmp/cpu.log & 11 | sar -n DEV 1 5 |grep '^Average:' > /tmp/net.log & 12 | echo -n "收集数据" 13 | for i in `seq 1 5` 14 | do 15 | echo -n "." 16 | sleep 1 17 | done 18 | echo 19 | 20 | t=`date +"%F %T"` 21 | load=`uptime |awk -F 'load averages?: ' '{print $2}'|cut -d '.' -f1` 22 | cpu_idle=`tail -1 /tmp/cpu.log|awk '{print $NF}'` 23 | cpu_use=`echo "scale=2;100-$cpu_idle"|bc` 24 | mem_tot=`free -m |grep '^Mem:'|awk '{print $2}'` 25 | mem_ava=`free -m |grep '^Mem:'|awk '{print $NF}'` 26 | mysql_p="dR6wB1jzq" 27 | echo -e "\033[32m当前时间:$t \033[0m" 28 | echo "######" 29 | echo -e "\033[31m当前负载:$load \033[0m" 30 | echo "######" 31 | echo -e "\033[33mCPU使用率:$cpu_use% \033[0m" 32 | echo "######" 33 | echo -e "\033[34m内存总数:$mem_tot"MB", 内存剩余:$mem_ava"MB" \033[0m" 34 | echo "######" 35 | echo -e "\033[35m磁盘空间使用情况:\033[0m" 36 | df -h 37 | echo "######" 38 | echo -e "\033[36m磁盘inode使用情况:\033[0m” 39 | df -i 40 | echo "######" 41 | sed '1d' /tmp/net.log |awk '{print "网卡"$2": 入口流量"$5/1000*8"Mbi, 出口流量"$6/1000*8"Mbi"}' 42 | echo "######" 43 | 44 | get_acc_log() 45 | { 46 | tail -100 /data/logs/www.log 47 | } 48 | 49 | get_mysql_slow_log() 50 | { 51 | tail -50 /data/mysql/slow.log 52 | } 53 | 54 | get_php_slow_log() 55 | { 56 | tail -50 /usr/local/php/logs/slow.log 57 | } 58 | 59 | restart_php() 60 | { 61 | /etc/init.d/php-fpm restart 62 | } 63 | 64 | restart_nginx() 65 | { 66 | /etc/init.d/nginx restart 67 | } 68 | 69 | get_mysql_process() 70 | { 71 | mysql -uroot -p$mysql_p -e "show processlist" 72 | } 73 | 74 | 75 | PS3="请选择你想要做的操作:" 76 | 77 | select c in 查看访问日志 查看mysql慢查询日志 查看php-fpm的慢执行日志 重启php-fpm服务 重启nginx服务 查看mysql队列 退出脚本 78 | do 79 | case $c in 80 | 查看访问日志) 81 | get_acc_log 82 | ;; 83 | 查看mysql慢查询日志) 84 | get_mysql_slow_log 85 | ;; 86 | 查看php-fpm的慢执行日志) 87 | get_php_slow_log 88 | ;; 89 | 重启php-fpm服务) 90 | restart_php 91 | ;; 92 | 重启nginx服务) 93 | restart_nginx 94 | ;; 95 | 查看mysql队列) 96 | get_mysql_process 97 | ;; 98 | 退出脚本) 99 | exit 0 100 | ;; 101 | esac 102 | done 103 | ``` 104 | -------------------------------------------------------------------------------- /codes/9.md: -------------------------------------------------------------------------------- 1 | #### 参考脚本 2 | ``` 3 | #!/bin/bash 4 | #监控网卡流量,当流量为0,重启网卡 5 | #作者:阿铭 6 | #日期:2018-10-07 7 | #版本:v0.2 8 | 9 | #设定语言为英文 10 | LANG=en 11 | 12 | #判定系统是否已经安装sysstat包,该包里有sar命令 13 | if ! rpm -q sysstat &>/dev/null 14 | then 15 | yum install -y sysstat 16 | fi 17 | 18 | #将10秒的网卡流量写入到一个临时文件里 19 | sar -n DEV 1 10 |grep 'eth0' > /tmp/eth0_sar.log 20 | 21 | #入口网卡流量 22 | net_in=`grep '^Average:' /tmp/eth0_sar.log|awk '{print $5}'` 23 | 24 | #出口网卡流量 25 | net_out=`grep '^Average:' /tmp/eth0_sar.log|awk '{print $6}'` 26 | 27 | #当入口和出口流量同时为0时,说明网卡异常 28 | if [ $net_in == "0.00" -a $net_out == "0.00" ] 29 | then 30 | echo "`date` eth0网卡出现异常,重启网卡。">> /tmp/net.log 31 | ifdown eth0 && ifup eth0 32 | fi 33 | ``` 34 | #### 扩展参考脚本 35 | ``` 36 | #!/bin/bash 37 | #监控网卡流量增幅超过一倍告警 38 | #作者:阿铭 39 | #日期:2018-10-07 40 | #版本:v0.1 41 | 42 | mail_user=admin@admin.com 43 | dir=/tmp/netlog 44 | 45 | [ -d $dir ] || mkdir $dir 46 | s_m=`lsattr -d $dir|awk '{print $1}' |sed 's/[^a]//g'` 47 | if [ $s_m != "a" ] 48 | then 49 | chattr +a $dir 50 | fi 51 | 52 | if ! rpm -q sysstat &>/dev/null 53 | then 54 | yum install -y sysstat 55 | fi 56 | 57 | sar -n DEV 1 10 |grep 'eth0' > /tmp/eth0_sar.log 58 | net_in=`grep '^Average:' /tmp/eth0_sar.log|awk '{print $5}'` 59 | net_out=`grep '^Average:' /tmp/eth0_sar.log|awk '{print $6}'` 60 | 61 | if [ ! -f $dir/net.log ] 62 | then 63 | echo "net_in $net_in" >> $dir/net.log 64 | echo "net_out $net_out" >> $dir/net.log 65 | exit 0 66 | fi 67 | 68 | net_in_last=`tail -2 $dir/net.log|grep 'net_in'` 69 | net_out_last=`tail -2 $dir/net.log|grep 'net_out'` 70 | net_in_diff=`$[$net_in-$net_in_last]` 71 | net_out_diff=`$[$net_out-$net_out_last]` 72 | 73 | if [ $net_in_diff -gt $net_in_last ] 74 | then 75 | python mail.py $mail_user "网卡入口流量增幅异常" "增幅$net_in_diff" 76 | #这里的mail.py参考案例二的知识点五 77 | fi 78 | 79 | if [ $net_out_diff -gt $net_out_last ] 80 | then 81 | python mail.py $mail_user "网卡出口流量增幅异常" "增幅$net_out_diff" 82 | fi 83 | 84 | echo "net_in $net_in" >> $dir/net.log 85 | echo "net_out $net_out" >> $dir/net.log 86 | ``` 87 | --------------------------------------------------------------------------------