i;j--)) do echo -n " " done..._linux script %y%m%d script">
当前位置:   article > 正文

101个shell脚本

linux script %y%m%d script

本文用于记录学习和日常中使用过的shell脚本

【脚本1】打印形状

打印等腰三角形、直角三角形、倒直角三角形、菱形

  1. #!/bin/bash
  2. # 等腰三角形
  3. read -p "Please input the length: " n
  4. for i in `seq 1 $n`
  5. do
  6. for ((j=$n;j>i;j--))
  7. do
  8. echo -n " "
  9. done
  10. for m in `seq 1 $i`
  11. do
  12. echo -n "* "
  13. done
  14. echo
  15. done
  16. # 倒直角三角形
  17. read -p "Please input the length: " len
  18. for i in `seq 1 $len`
  19. do
  20. for j in `seq $i $len`
  21. do
  22. echo -n "* "
  23. done
  24. echo
  25. done
  26. # 直角三角形
  27. read -p "Please input the length: " len
  28. for i in `seq 1 $len`
  29. do
  30. for((j=1;j<=$i;j++))
  31. do
  32. echo -n "* "
  33. done
  34. echo
  35. done
  36. # 菱形
  37. read -p "Please input the length: " n
  38. for i in `seq 1 $n`
  39. do
  40. for ((j=$n;j>i;j--))
  41. do
  42. echo -n " "
  43. done
  44. for m in `seq 1 $i`
  45. do
  46. echo -n "* "
  47. done
  48. echo
  49. done
  50. for i in `seq 1 $n`
  51. do
  52. for((j=1;j<=$i;j++))
  53. do
  54. echo -n " "
  55. done
  56. for((k=$i;k<=$len-1;k++))
  57. do
  58. echo -n "* "
  59. done
  60. echo
  61. done

【脚本2】截取字符串

现有一个字符串如下:

http://www.aaa.com/root/123.htm

请根据以下要求截取出字符串中的字符:

1.取出www.aaa.com/root/123.htm

2.取出123.htm

3.取出http://www.aaa.com/root

4.取出http:

5.取出http://

6.取出www.aaa.com/root/123.htm

7.取出123

8.取出123.htm

  1. #!/bin/bash
  2. var="http://www.aaa.com/root/123.htm"
  3. #1.
  4. echo $var |awk -F '//' '{print $2}'
  5. #2.
  6. echo $var |awk -F '/' '{print $5}'
  7. #3.
  8. echo $var |grep -o 'http.*root'
  9. #4.
  10. echo $var |awk -F '/' '{print $1}'
  11. #5.
  12. echo $var |grep -o 'http://'
  13. #6.
  14. echo $var |grep -o 'www.*htm'
  15. #7.
  16. echo $var |grep -o '123'
  17. #8.
  18. echo $var |grep -o '123.htm'

【脚本3】tomcat启动脚本

emm。。这个脚本是因为tomcat没有自带的能够给service开机启动的脚本,我就琢磨着自己写了一个简单的启动脚本,如下:

  1. #!/bin/bash
  2. # chkconfig:2345 64 36
  3. # description: Tomcat start/stop/restart script.
  4. ### BEGIN INIT INFO
  5. # Provides: tomcat
  6. # Required-Start:
  7. # Should-Start:
  8. # Required-Stop:
  9. # Default-Start: 2 3 4 5
  10. # Default-Stop: 0 1 6
  11. # Short-Description: start and stop Tomcat
  12. # Description: Tomcat Service start&restart&stop script
  13. ### END INIT INFO
  14. ##Written by zero.##
  15. JAVA_HOME=/usr/local/jdk1.8/
  16. JAVA_BIN=/usr/local/jdk1.8/bin
  17. JRE_HOME=/usr/local/jdk1.8/jre
  18. PATH=$PATH:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/jre/bin
  19. CLASSPATH=/usr/local/jdk1.8/jre/lib:/usr/local/jdk1.8/lib:/usr/local/jdk1.8/jre/lib/charsets.jar
  20. TOMCAT_BIN=/usr/local/tomcat/bin
  21. RETVAL=0
  22. prog="Tomcat"
  23. start()
  24. {
  25. echo "Starting $prog......"
  26. /bin/bash $TOMCAT_BIN/startup.sh
  27. RETVAL=$?
  28. return $RETVAL
  29. }
  30. stop()
  31. {
  32. echo "Stopping $prog......"
  33. /bin/bash $TOMCAT_BIN/shutdown.sh
  34. RETVAL=$?
  35. return $RETVAL
  36. }
  37. restart(){
  38. echo "Restarting $prog......"
  39. stop
  40. start
  41. }
  42. case "$1" in
  43. start)
  44. start
  45. ;;
  46. stop)
  47. stop
  48. ;;
  49. restart)
  50. restart
  51. ;;
  52. *)
  53. echo $"Usage: $0 {start|stop|restart}"
  54. RETVAL=1
  55. esac
  56. exit $RETVAL

【脚本4】自定义rm命令

linux系统的rm命令太危险,一不小心就会删除掉系统文件。 写一个shell脚本来替换系统的rm命令,要求当删除一个文件或者目录时,都要做一个备份,然后再删除。下面分两种情况,做练习:

1. 简单的实现:

假设有一个大的分区/data/,每次删除文件或者目录之前,都要先在/data/下面创建一个隐藏目录,以日期/时间命名,比如/data/.201703271012/,然后把所有删除的文件同步到该目录下面,可以使用rsync -R 把文件路径一同同步,示例:

  1. #!/bin/bash
  2. fileName=$1
  3. now=`date +%Y%m%d%H%M`
  4. read -p "Are you sure delete the file or directory $1? yes|no: " input
  5. if [ $input == "yes" ] || [ $input == "y" ]
  6. then
  7. mkdir /data/.$now
  8. rsync -aR $1/ /data/.$now/$1/
  9. /bin/rm -rf $1
  10. elif [ $input == "no" ] || [ $input == "n" ]
  11. then
  12. exit 0
  13. else
  14. echo "Only input yes or no"
  15. exit
  16. fi

2.复杂的实现:

不知道哪个分区有剩余空间,在删除之前先计算要删除的文件或者目录大小,然后对比系统的磁盘空间,如果够则按照上面的规则创建隐藏目录,并备份,如果没有足够空间,要提醒用户没有足够的空间备份并提示是否放弃备份,如果用户输入yes,则直接删除文件或者目录,如果输入no,则提示未删除,然后退出脚本,示例:

  1. #!/bin/bash
  2. fileName=$1
  3. now=`date +%Y%m%d%H%M`
  4. f_size=`du -sk $1 |awk '{print $1}'`
  5. disk_size=`LANG=en; df -k |grep -vi filesystem |awk '{print $4}' |sort -n |tail -n1`
  6. big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk '{print $NF}'`
  7. if [ $f_size -lt $disk_size ]
  8. then
  9. read -p "Are you sure delete the file or directory: $1 ? yes|no: " input
  10. if [ $input == "yes" ] || [ $input == "y" ]
  11. then
  12. mkdir -p $big_filesystem/.$now && rsync -aR $1 $big_filesystem/.$now/ && /bin/rm -rf $1
  13. elif [ $input == "no" ] || [ $input == "n" ]
  14. then
  15. exit 0
  16. else
  17. echo "Only input 'yes' or 'no'."
  18. fi
  19. else
  20. echo "The disk size is not enough to backup the file: $1."
  21. read -p "Do you want to delete "$1"? yes|no: " input
  22. if [ $input == "yes" ] || [ $input == "y" ]
  23. then
  24. echo "It will delete "$1" after 5 seconds whitout backup."
  25. for i in `seq 1 5`; do echo -ne "."; sleep 1; done
  26. echo
  27. /bin/rm -rf $1
  28. elif [ $input == "no" ] || [ $input == "n" ]
  29. then
  30. echo "It will not delete $1."
  31. exit 0
  32. else
  33. echo "Only input 'yes' or 'no'."
  34. fi
  35. fi

【脚本5】数字求和

编写shell脚本,要求输入一个数字,然后计算出从1到输入数字的和,要求,如果输入的数字小于1,则重新输入,直到输入正确的数字为止,示例:

  1. #!/bin/bash
  2. while :
  3. do
  4. read -p "Please enter a positive integer: " n
  5. if [ $n -lt 1 ]
  6. then
  7. echo "It can't be less than 1"
  8. else
  9. break
  10. fi
  11. done
  12. num=1
  13. for i in `seq 2 $n`
  14. do
  15. num=$[$num+$i]
  16. done
  17. echo $num

【脚本6】拷贝目录

编写shell脚本,把/root/目录下的所有目录(只需要一级)拷贝到/tmp/目录下:

  1. #!/bin/bash
  2. cd /root/
  3. list=(`ls`)
  4. for i in ${list[@]}
  5. do
  6. if [ -d $i ]
  7. then
  8. cp -r $i /tmp/
  9. fi
  10. done

【脚本7】批量建立用户

编写shell脚本,批量建立用户user_00, user_01, ... user_100并且所有用户同属于users组:

  1. #!/bin/bash
  2. group=`cat /etc/group |grep -o users`
  3. if [ $group == "users" ]
  4. then
  5. for i in `seq 0 100`
  6. do
  7. if [ $i -lt 10 ]
  8. then
  9. useradd -g users user_0$i
  10. else
  11. useradd -g users user_$i
  12. fi
  13. done
  14. else
  15. echo "users group not found!"
  16. exit 1
  17. fi

删除以上脚本批量添加的用户:

  1. #!/bin/bash
  2. for i in `seq 0 100`
  3. do
  4. if [ $i -lt 10 ]
  5. then
  6. userdel -r user_0$i
  7. else
  8. userdel -r user_$i
  9. fi
  10. done

【脚本8】每日生成一个文件

要求:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron,仅仅写脚本即可)

  1. #!/bin/bash
  2. fileName=`date +%F`
  3. c=`df -h`
  4. echo "$c" > /root/$fileName.log

【脚本9】统计ip

有一个日志文件,日志片段:如下:

112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com “/seccode.php?update=0.5593110133088248″ 200″http://formula-x.haotui.com/registerbbs.php” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)”
61.147.76.51 – [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com “/attachment.php?aid=4554&k=9ce51e2c376bc861603c7689d97c04a1&t=1334564048&fid=9&sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71″ 301″http://xyzdiy.×××thread-1435-1-23.html” “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”

要求: 统计出每个IP的访问量有多少?

awk '{print $1}' 1.log |sort -n |uniq -c |sort -n

解释:sort -n会按照数值而不是ASCII码来排序awk截取出来的IP。然后uniq命令用于报告或忽略文件中的重复行,加上-c选项后会在每列旁边显示该行重复出现的次数,在这一步就完成了统计。不过最后还得再让sort -n排序一下uniq -c统计出来的结果。


【脚本10】统计内存使用

写一个脚本计算一下linux系统所有进程占用内存大小的和。

实现代码:

  1. #!/bin/bash
  2. count=0
  3. # 这个循环会遍历出每个进程占用的内存大小
  4. for i in `ps aux |awk '{print $6}' |grep -v 'RSS'`
  5. do
  6. # 将遍历出来的数字进行累加
  7. count=$[$count+$i]
  8. done
  9. # 就得到所有进程占用内存大小的和了
  10. echo "$count/kb"

也可以使用awk 一条命令计算:

ps aux |grep -v 'RSS TTY' |awk '{sum=sum+$6};END{print sum}'

解释:grep -v是忽略 'RSS TTY' 所存在的那一行,后面的awk声明了一个变量sum,sum将前面命令列出来的数字进行累加,END之后就将累加后的sum打印出来,就得到所有进程占用内存大小的和了。


【脚本11】简单的监控脚本

设计一个简单的脚本,监控远程的一台机器(假设ip为123.23.11.21)的存活状态,当发现宕机时发一封邮件给你自己。

  1. #!/bin/bash
  2. ip="123.23.11.21"
  3. email="user@example"
  4. while 1
  5. do
  6. ping -c10 $ip > /dev/null 2>/dev/null
  7. if [ $? != "0" ]
  8. then
  9. # 调用一个用于发邮件的脚本
  10. python /usr/local/sbin/mail.py $email "$ip down" "$ip is down"
  11. fi
  12. sleep 30
  13. done

mail.py 脚本代码:

  1. #!/usr/bin/env python
  2. #-*- coding: UTF-8 -*-
  3. import os,sys
  4. reload(sys)
  5. sys.setdefaultencoding('utf8')
  6. import getopt
  7. import smtplib
  8. from email.MIMEText import MIMEText
  9. from email.MIMEMultipart import MIMEMultipart
  10. from subprocess import *
  11. def sendqqmail(username,password,mailfrom,mailto,subject,content):
  12. # 邮箱的服务地址
  13. gserver = 'smtp.qq.com'
  14. gport = 25
  15. try:
  16. msg = MIMEText(unicode(content).encode('utf-8'))
  17. msg['from'] = mailfrom
  18. msg['to'] = mailto
  19. msg['Reply-To'] = mailfrom
  20. msg['Subject'] = subject
  21. smtp = smtplib.SMTP(gserver, gport)
  22. smtp.set_debuglevel(0)
  23. smtp.ehlo()
  24. smtp.login(username,password)
  25. smtp.sendmail(mailfrom, mailto, msg.as_string())
  26. smtp.close()
  27. except Exception,err:
  28. print "Send mail failed. Error: %s" % err
  29. def main():
  30. to=sys.argv[1]
  31. subject=sys.argv[2]
  32. content=sys.argv[3]
  33. #定义QQ邮箱的账号和密码,你需要修改成你自己的账号和密码
  34. sendqqmail('1234567@qq.com','aaaaaaaaaa','1234567@qq.com',to,subject,content)
  35. if __name__ == "__main__":
  36. main()
  37. #####脚本使用说明######
  38. #1. 首先定义好脚本中的邮箱账号和密码
  39. #2. 脚本执行命令为:python mail.py 目标邮箱 "邮件主题" "邮件内容"

【脚本12】批量更改文件名

需求:

  • 找到/123目录下所有后缀名为.txt的文件
  • 批量修改.txt为.txt.bak
  • 把所有.bak文件打包压缩为123.tar.gz
  • 批量还原文件的名字,即把增加的.bak再删除

代码:

  1. #!/bin/bash
  2. now=`date +%F_%T`
  3. mkdir /tmp/123_$now
  4. for txt in `ls /123/*.txt`
  5. do
  6. mv $txt $txt.bak
  7. for f in $txt
  8. do
  9. cp $txt.bak /tmp/123_$now
  10. done
  11. done
  12. cd /tmp/
  13. tar czf 123.tar.gz 123_$now/
  14. for txt in `ls /123/*.txt.bak`
  15. do
  16. name=`echo $txt |awk -F '.' '{OFS="."} {print $1,$2}'`
  17. mv $txt $name
  18. done

【脚本13】监控80端口

需求:
写一个脚本,判断本机的80端口(假如服务为httpd)是否开启着,如果开启着什么都不做,如果发现端口不存在,那么重启一下httpd服务,并发邮件通知你自己。脚本写好后,可以每一分钟执行一次,也可以写一个死循环的脚本,30s检测一次。
发邮件的脚本参考【脚本11】的示例代码。
代码:

  1. #!/bin/bash
  2. email="user@example.com"
  3. if netstat -lntp |grep ':80' |grep 'httpd'
  4. then
  5. echo "80 port no problem"
  6. exit
  7. else
  8. /usr/local/apache2.4/bin/apachectl restart
  9. python mail.py $email "check_80port" "The 80 port is down."
  10. n=`ps aux |grep httpd|grep -cv grep`
  11. if [ $n -eq 0 ]
  12. then
  13. /usr/local/apache2/bin/apachectl start 2>/tmp/apache_start.err
  14. fi
  15. if [ -s /tmp/apache_start.err ]
  16. then
  17. python mail.py $mail 'apache_start_error' `cat /tmp/apache_start.err`
  18. fi
  19. fi

【脚本14】备份数据库

需求:

设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30,远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup . 写完脚本后,需要加入到cron中,每天凌晨3点执行。
脚本代码:

  1. #!/bin/bash
  2. PATH=$PATHi:/usr/local/mysql/bin
  3. week=`date +%w`
  4. today=`date +d`
  5. passwd="123456"
  6. backdir="/data/mysql"
  7. r_backupIP="192.168.123.30::backup"
  8. exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log
  9. echo "mysql backup begin at `date +%F %T`."
  10. # 本地备份
  11. mysqldump -uroot -p$passwd --default-character-set=utf8 discuz >$backdir/$week.sql
  12. # 同步备份到远程机器
  13. rsync -az $backdir/$week.sql $r_backupIP/$today.sql
  14. echo "mysql backup end at `date +%F %T`."

然后加入cron
0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh


【脚本15】自动重启php-fpm服务

服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。

我们设定:

  1. access_log /data/log/access.log
  2. 脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)
  3. 重启php-fpm的方法是 /etc/init.d/php-fpm restart

脚本代码:

  1. #!/bin/bash
  2. access_log="/data/log/access.log"
  3. N=10
  4. while :
  5. do
  6. # 因为10秒大概产生300条日志记录
  7. tail -n300 $access_log > /tmp/log
  8. # 拿出log中包含502的日志行数
  9. n_502=`grep -c "502" /tmp/log`
  10. # 如果行数大于10
  11. if [ $n_502 -ge $N ]
  12. then
  13. # 就记录一下系统状态
  14. top -bn1 > /tmp/`date +%H%M%S`-top.log
  15. vmstat 1 5 > /tmp/`date +%H%M%S`-vm.log
  16. # 然后才重启服务,并把错误信息重定向
  17. /etc/init.d/php-fpm restart 2> /dev/null
  18. # 重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次
  19. sleep(60)
  20. fi
  21. sleep(10)
  22. done

【脚本16】文本替换

将memcached里的数据导出到文件中,然后再导入memcached里却发现数据过期了,这是因为导出的数据是带有一个时间戳的,这个时间戳就是该条数据过期的时间点,如果当前时间已经超过该时间戳,那么是导入不进去的。不过可以修改文件中的时间戳来保证导入时数据的有效期。可以写一个简单的脚本批量替换这些文件中的时间戳:

  1. #!/bin/bash
  2. hour=`date -d "+1 hour" +%s` # 一个小时之后的时间戳
  3. data_time=`cat data.txt |grep add |awk '{print $4}' |sort -n |uniq`
  4. for i in $data_time
  5. do
  6. sed -i "s/$i/$hour/g" `grep $i -rl /root/data.txt`
  7. done

【脚本17】启动容器

docker每次关闭都会连带着将运行中的容器关闭,所以每次启动docker后都需要逐个去启动容器,很麻烦,由于是实验用的虚拟机不是线上的机器,所以就直接写了一个很简单的循环来启动容器:

  1. #!/bin/bash
  2. /usr/bin/systemctl start docker
  3. for i in `docker ps -a |grep 'Exited' |awk '{print $1}'`
  4. do
  5. /usr/bin/docker start $i
  6. done

【脚本18】删除文本中的字母

要求:把一个文本文档的前5行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉。

参考答案:假设文本名字叫做1.txt,并且文本行数大于10,脚本如下:

  1. #!/bin/bash
  2. ## 先获取该文本的行数
  3. rows=`wc -l 1.txt |awk '{print $1}'`
  4. ## 对前5行进行处理
  5. for i in `seq 1 5`
  6. do
  7. ## 使用sed把每一行的内容赋值给变量
  8. row=`sed -n "$i"p 1.txt`
  9. ## 用grep 判定是否匹配字母,-v取反,-q不输出内容
  10. if echo $row |grep -vq '[a-zA-Z]'
  11. then
  12. echo $row
  13. fi
  14. done
  15. ## 对6-10行做删除字母处理
  16. for i in `seq 6 10`
  17. do
  18. row=`sed -n "$i"p 1.txt`
  19. echo $row |sed 's/[a-zA-Z]//g'
  20. done
  21. ## 剩余的直接输出
  22. for i in `seq 11 $rows`
  23. do
  24. sed -n "$i"p 1.txt
  25. done
  26. ##若想把更改内容写入到1.txt,还需要把以上内容重定向到一个文本中,然后删除1.txt,再把刚刚重定向的文件更名为1.txt

【脚本19】查找字母数小于6的单词

用shell打印下面这句话中字母数小于6的单词。
Bash also interprets a number of multi-character options.

脚本如下:

  1. #!/bin/bash
  2. for s in Bash also interprets a number of multi-character options
  3. do
  4. n=`echo $s |wc -c`
  5. if [ $n -lt 6 ]
  6. then
  7. echo $s
  8. fi
  9. done

【脚本20】输入数字执行对应命令

写一个脚本实现如下功能: 输入一个数字,然后运行对应的一个命令。显示命令如下:

*cmd meau** 1—date 2–ls 3–who 4–pwd

当输入1时,会运行date, 输入2时运行ls, 依此类推。

实现脚本如下:

  1. #!/bin/bash
  2. echo "*cmd meau** 1—date 2–ls 3–who 4–pwd"
  3. read -p "please input a number 1-4: " n
  4. case $n in
  5. 1)
  6. date
  7. ;;
  8. 2)
  9. ls
  10. ;;
  11. 3)
  12. who
  13. ;;
  14. 4)
  15. pwd
  16. ;;
  17. *)
  18. echo "Please input a number: 1-4"
  19. ;;
  20. esac

【脚本21】批量创建用户并设置密码

用shell脚本实现如下需求:
添加user_00 – user_09 10个用户,并且给他们设置一个随机密码,密码要求10位包含大小写字母以及数字,注意需要把每个用户的密码记录到一个日志文件里。

提示:

  1. 随机密码使用命令 mkpasswd
  2. 在脚本中给用户设置密码,可以使用echo 然后管道passwd命令

实现脚本如下:

  1. #!/bin/bash
  2. for i in `seq 00 09`
  3. do
  4. useradd user_$i
  5. p=`mkpasswd -s 0 -l 10`
  6. echo "user_$i $p" >> /tmp/user0_9.pw
  7. echo $p |passwd -stdin user_$i
  8. done

【脚本22】监控httpd进程

在服务器上,写一个监控脚本。

  1. 每隔10s去检测一次服务器上的httpd进程数,如果大于等于500的时候,就需要自动重启一下apache服务,并检测启动是否成功?
  2. 若没有正常启动还需再一次启动,最大不成功数超过5次则需要理解发邮件通知管理员,并且以后不需要再检测!
  3. 如果启动成功后,1分钟后再次检测httpd进程数,若正常则重复之前操作(每隔10s检测一次),若还是大于等于500,那放弃重启并需要发邮件给管理员,然后自动退出该脚本。假设其中发邮件脚本为mail.py

实现脚本如下:

  1. #!/bin/bash
  2. check_service(){
  3. n=0
  4. for i in `seq 1 5`
  5. do
  6. # apachectl命令所在路径
  7. /usr/local/apache2/bin/apachectl restart 2> /tmp/apache.err
  8. if [$? -ne 0 ]
  9. then
  10. n=$[$n-1]
  11. else
  12. break
  13. fi
  14. done
  15. if [ $n -eq 5 ]
  16. then
  17. ## mail.py的内容参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py
  18. python mail.py "123@qq.com" "httpd service down" `cat /tmp/apache.err`
  19. exit
  20. fi
  21. }
  22. while :
  23. do
  24. t_n=`ps -C httpd --no-heading |wc -l`
  25. if [ $t_n -ge 500 ]
  26. then
  27. /usr/local/apache2/bin/apachectl restart
  28. if [ $? -ne 0 ]
  29. then
  30. check_service
  31. fi
  32. sleep 60
  33. t_n=`ps -C httpd --no-heading |wc -l`
  34. if [ $t_n -ge 500]
  35. then
  36. python mail.py "123@qq.com" "httpd service somth wrong" "the httpd process is budy."
  37. exit
  38. fi
  39. fi
  40. sleep 10
  41. done

【脚本23】封ip

需求: 根据web服务器上的访问日志,把一些请求量非常高的ip给拒绝掉!

分析: 我们要做的,不仅是要找到哪些ip请求量不合法,并且还要每隔一段时间把之前封掉的ip(若不再继续请求了)给解封。 所以该脚本的关键点在于定一个合适的时间段和阈值。

比如, 我们可以每一分钟去查看一下日志,把上一分钟的日志给过滤出来分析,并且只要请求的ip数量超过100次那么就直接封掉。 而解封的时间又规定为每半小时分析一次,把几乎没有请求量的ip给解封!

参考日志文件片段:

  1. 157.55.39.107 [20/Mar/2015:00:01:24 +0800] www.aminglinux.com “/bbs/thread-5622-3-1.html” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”
  2. 61.240.150.37 [20/Mar/2015:00:01:34 +0800] www.aminglinux.com “/bbs/search.php?mod=forum&srchtxt=LNMP&formhash=8f0c7da9&searchsubmit=true&source=hotsearch” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”

脚本实现如下:

  1. #!/bin/bash
  2. ## 日志文件路径
  3. log_file="/home/logs/client/access.log"
  4. ## 当前时间减一分钟的时间
  5. d1=`date -d "-1 minute" +%H:%M`
  6. ## 当前时间的分钟段
  7. d2=`date +%M`
  8. ## iptables命令所在的路径
  9. ipt="/sbin/iptables"
  10. ## 用于存储访问日志里的ip
  11. ips="/tmp/ips.txt"
  12. ## 封ip
  13. block(){
  14. ## 把日志文件中的ip过滤出来,去掉重复的ip,并统计ip的重复次数以及对ip进行排序,最后将结果写到一个文件中
  15. grep "$d1:" $log_file |awk '{print $1}' |sort -n |uniq -c |sort -n > $ips
  16. ## 将文件里重复次数大于100的ip迭代出来
  17. for ip in `awk '$1 > 100 {print $2}' $ips`
  18. do
  19. ## 通过防火墙规则对这些ip进行封禁
  20. $ipt -I INPUT -p -tcp --dport 80 -s $ip -j REJECT
  21. ## 将已经封禁的ip输出到一个文件里存储
  22. echo "`date +%F-%T` $ip" >> /tmp/badip.txt
  23. done
  24. }
  25. ## 解封ip
  26. unblock(){
  27. ## 将流量小于15的规则索引过滤出来
  28. for i in `$ipt -nvL --line-number |grep '0.0.0.0/0' |awk '$2 < 15 {print $1}' |sort -nr`
  29. do
  30. ## 通过索引来删除规则
  31. $ipt -D INPUT $i
  32. done
  33. ## 清空规则中的数据包计算器和字节计数器
  34. $ipt -Z
  35. }
  36. ## 为整点或30分钟就是过了半个小时,就需要再进行分析
  37. if [ $d2 == "00" ] || [ $d2 == "30" ]
  38. then
  39. unblock
  40. block
  41. else
  42. block
  43. fi

【脚本24】部署前端项目

最近做了一个web前端的项目,需要编写一个脚本完成项目的上线。

脚本实现如下:

  1. #!/bin/bash
  2. #
  3. # 使用方法:
  4. # mmall:front_deploy.sh mmall-fe
  5. # admin:front_deploy.sh admin-fe
  6. #
  7. GIT_HOME=/developer/git-repository/ # 从git仓库拉取下来的源码的存放路径
  8. DEST_PATH=/product/frontend/ # 项目打包后的发布路径
  9. # cd dir
  10. if [ ! -n "$1" ]
  11. then
  12. echo -e "请输入要发布的项目!"
  13. exit
  14. fi
  15. if [ $1 = "mmall-fe" ]
  16. then
  17. echo -e "===========Enter mall-fe============="
  18. cd $GIT_HOME$1
  19. elif [ $1 = "admin-fe" ]
  20. then
  21. echo -e "===========Enter mall-fe============="
  22. cd $GIT_HOME$1
  23. else
  24. echo -e "输入的项目名没有找到!"
  25. exit
  26. fi
  27. # clear git dist
  28. echo -e "===========Clear Git Dist============="
  29. rm -rf ./dist
  30. # git操作
  31. echo -e "===========git checkout master============="
  32. git checkout master
  33. echo -e "===========git pull============="
  34. git pull
  35. # npm install
  36. echo -e "===========npm install============="
  37. npm install --registry=https://registry.npm.taobao.org
  38. # npm run dist
  39. echo -e "===========npm run dist============="
  40. npm run dist
  41. if [ -d "./dist" ]
  42. then
  43. # backup dest
  44. echo -e "===========dest backup============="
  45. mv $DEST_PATH$1/dist $DEST_PATH$1/dist.bak
  46. # copy
  47. echo -e "===========copy============="
  48. cp -R ./dist $DEST_PATH$1
  49. # echo result
  50. echo -e "===========Deploy Success============="
  51. else
  52. echo -e "===========Deploy Error============="
  53. fi

【脚本25】找规律打印数字

请详细查看如下几个数字的规律,并使用shell脚本输出后面的十个数字。

10 31 53 77 105 141 …….

试题解析:
我想大多数人都会去比较这些数字的差值:

  1. 10 31 53 77 105 141
  2. 21 22 24 28 36

但是这个差值看,并没有什么规律,而我们再仔细看的时候,发现这个差值的差值是有规律的:

  1. 10 31 53 77 105 141
  2. 21 22 24 28 36
  3. 1 2 4 8

脚本实现:

  1. #! /bin/bash
  2. x=21
  3. m=10
  4. echo $m
  5. for i in `seq 0 14`; do
  6. j=$[2**$i]
  7. m=$[$m+$x]
  8. echo $m
  9. x=$[$x+$j]
  10. done

【脚本26】统计普通用户

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

假设所有普通用户都是uid大于1000的

脚本实现:

  1. #!/bin/bash
  2. n=`awk -F ':' '$3>1000' /etc/passwd|wc -l`
  3. if [ $n -gt 0 ]
  4. then
  5. echo "There are $n common users."
  6. else
  7. echo "No common users."
  8. fi

【脚本27】监控磁盘使用率

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

思路:就是先df -h 然后过滤出已使用的那一列,然后再想办法过滤出百分比的整数部分,然后和85去比较,同理,inode也是一样的思路。

实现代码:

  1. #!/bin/bash
  2. ## This script is for record Filesystem Use%,IUse% everyday and send alert mail when % is more than 85%.
  3. log=/var/log/disk/`date +%F`.log
  4. date +'%F %T' > $log
  5. df -h >> $log
  6. echo >> $log
  7. df -i >> $log
  8. for i in `df -h|grep -v 'Use%'|sed 's/%//'|awk '{print $5}'`; do
  9. if [ $i -gt 85 ]; then
  10. use=`df -h|grep -v 'Use%'|sed 's/%//'|awk '$5=='$i' {print $1,$5}'`
  11. echo "$use" >> use
  12. fi
  13. done
  14. if [ -e use ]; then
  15. ##这里可以使用咱们之前介绍的mail.py发邮件
  16. mail -s "Filesystem Use% check" root@localhost < use
  17. rm -rf use
  18. fi
  19. for j in `df -i|grep -v 'IUse%'|sed 's/%//'|awk '{print $5}'`; do
  20. if [ $j -gt 85 ]; then
  21. iuse=`df -i|grep -v 'IUse%'|sed 's/%//'|awk '$5=='$j' {print $1,$5}'`
  22. echo "$iuse" >> iuse
  23. fi
  24. done
  25. if [ -e iuse ]; then
  26. mail -s "Filesystem IUse% check" root@localhost < iuse
  27. rm -rf iuse
  28. fi

思路:

  1. df -h、df -i 记录磁盘分区使用率和inode使用率,date +%F 日志名格式
  2. 取出使用率(第5列)百分比序列,for循环逐一与85比较,大于85则记录到新文件里,当for循环结束后,汇总超过85的一并发送邮件(邮箱服务因未搭建,发送本地root账户)。

此脚本正确运行前提:

  • 该系统没有逻辑卷的情况下使用,因为逻辑卷df -h、df -i 时,使用率百分比是在第4列,而不是第5列。如有逻辑卷,则会漏统计逻辑卷使用情况。

【脚本28】获取文件列表

有一台服务器作为web应用,有一个目录(/data/web/attachment)不定时地会被用户上传新的文件,但是不知道什么时候会上传。所以,需要我们每5分钟做一次检测是否有新文件生成。

请写一个shell脚本去完成检测。检测完成后若是有新文件,还需要将新文件的列表输出到一个按年、月、日、时、分为名字的日志里。请不要想的太复杂,核心命令只有一个 find /data/web/attachment -mmin -5

思路: 每5分钟检测一次,那肯定需要有一个计划任务,每5分钟去执行一次。脚本检测的时候,就是使用find命令查找5分钟内有过更新的文件,若是有更新,那这个命令会输出东西,否则是没有输出的。固,我们可以把输出结果的行数作为比较对象,看看它是否大于0。

实现代码:

  1. #!/bin/bash
  2. d=`date -d "-5 min" +%Y%m%d%H%M`
  3. basedir=/data/web/attachment
  4. find $basedir/ -type f -mmin -5 > /tmp/newf.txt
  5. n=`wc -l /tmp/newf.txt`
  6. if [ $n -gt 0 ]; then
  7. /bin/mv /tmp/newf.txt /tmp/$d
  8. fi

【脚本29】统计常用命令

写一个shell脚本来看看你使用最多的命令是哪些,列出你最常用的命令top10。

思路:我们要用到一个文件就是.bash_history,然后再去sort、uniq,剩下的就不用我多说了吧。很简单一个shell。

一条命令即可:
sort /root/.bash_history |uniq -c |sort -nr |head


【脚本30】统计日志大小

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

实现代码:

  1. #!/bin/bash
  2. logdir="/data/log"
  3. t=`date +%H`
  4. d=`date +%F-%H`
  5. [ -d /tmp/log_size ] || mkdir /tmp/log_size
  6. for log in `find $logdir -type f`
  7. do
  8. if [ $t == "0" ] || [ $t == "12" ]
  9. then
  10. true > $log
  11. else
  12. du -sh $log >>/tmp/log_size/$d
  13. fi
  14. done

【脚本31】统计数字并求和

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

  1. 12aa*lkjskdj
  2. alskdflkskdjflkjj

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

bash ncount.sh a.txt

输入结果应该为:

  1. 2
  2. 0
  3. sum:2

实现代码:

  1. #!/bin/bash
  2. n=`wc -l a.txt|awk '{print $1}'`
  3. sum=0
  4. for i in `seq 1 $n`
  5. do
  6. line=`sed -n "$i"p a.txt`
  7. n_n=`echo -n $line|sed 's/[^0-9]//g'|wc -c`
  8. echo line $i number: $n_n
  9. sum=$[$sum+$n_n]
  10. done
  11. echo sum is $sum

【脚本32】检测文件改动

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

提示: 使用核心命令 md5sum a.txt 算出md5值,去和B机器上的比较。

实现代码:

  1. #!/bin/bash
  2. #假设A机器到B机器已经做了无密码登录设置
  3. dir=/data/web
  4. ##假设B机器的IP为192.168.0.100
  5. B_ip=192.168.0.100
  6. find $dir -type f |xargs md5sum >/tmp/md5.txt
  7. ssh $B_ip "find $dir -type f |xargs md5sum >/tmp/md5_b.txt"
  8. scp $B_ip:/tmp/md5_b.txt /tmp
  9. for f in `awk '{print $2}' /tmp/md5.txt`
  10. do
  11. if grep -q "$f" /tmp/md5_b.txt
  12. then
  13. md5_a=`grep $f /tmp/md5.txt|awk '{print $1}'`
  14. md5_b=`grep $f /tmp/md5_b.txt|awk '{print $1}'`
  15. if [ $md5_a != $md5_b ]
  16. then
  17. echo "$f changed."
  18. fi
  19. else
  20. echo "$f deleted. "
  21. fi
  22. done

【脚本33】统计网卡流量

写一个脚本,检测你的网络流量,并记录到一个日志里。需要按照如下格式,并且一分钟统计一次(只需要统计外网网卡,假设网卡名字为eth0):

  1. 2017-08-04 01:11
  2. eth0 input: 1000bps
  3. eth0 output : 200000bps
  4. ################
  5. 2017-08-04 01:12
  6. eth0 input: 1000bps
  7. eth0 output : 200000bps

提示:使用sar -n DEV 1 59 这样可以统计一分钟的平均网卡流量,只需要最后面的平均值。另外,注意换算一下,1byt=8bit

实现代码:

  1. #!/bin/bash
  2. while :
  3. do
  4. LANG=en
  5. DATE=`date +"%Y-%m-%d %H:%M"`
  6. LOG_PATH=/tmp/traffic_check/`date +%Y%m`
  7. LOG_FILE=$LOG_PATH/traffic_check_`date +%d`.log
  8. [ -d $LOG_PATH ] || mkdir -p $LOG_PATH
  9. echo " $DATE" >> $LOG_FILE
  10. sar -n DEV 1 59|grep Average|grep eth0 \
  11. |awk '{print "\n",$2,"\t","input:",$5*1000*8,"bps", \
  12. "\t","\n",$2,"\t","output:",$6*1000*8,"bps" }' \
  13. >> $LOG_FILE
  14. echo "#####################" >> $LOG_FILE
  15. done

【脚本34】系统-批量杀进程

今天发现网站访问超级慢,top看如下:
101个shell脚本

有很多sh进程,再ps查看:
101个shell脚本

这个脚本,运行很慢,因为制定了cron,上一次还没有运行完,又有了新的运行任务。太多肯定会导致系统负载升高。当务之急就是先把这些在跑的给kill掉。那么我们可以使用一条命令,直接杀死所有的sh。

命令如下:

ps aux |grep clearmem.sh |grep -v grep|awk '{print $2}'|xargs kill

【脚本35】判断是否开启80端口

写一个脚本判断你的Linux服务器里是否开启web服务?(监听80端口)如果开启了,请判断出跑的是什么服务,是httpd呢还是nginx又或者是其他的什么?

实现代码:

  1. #!/bin/bash
  2. port=`netstat -lnp | grep 80`
  3. if [ -z "port" ]; then
  4. echo "not start service.";
  5. exit;
  6. fi
  7. web_server=`echo $port | awk -F'/' '{print $2}'|awk -F : '{print $1}'`
  8. case $web_server in
  9. httpd )
  10. echo "apache server."
  11. ;;
  12. nginx )
  13. echo "nginx server."
  14. ;;
  15. * )
  16. echo "other server."
  17. ;;
  18. esac

【脚本36】监控mysql服务

假设,当前MySQL服务的root密码为123456,写脚本检测MySQL服务是否正常(比如,可以正常进入mysql执行show processlist),并检测一下当前的MySQL服务是主还是从,如果是从,请判断它的主从服务是否异常。如果是主,则不需要做什么。

实现代码:

  1. #!/bin/bash
  2. Mysql_c="mysql -uroot -p123456"
  3. $Mysql_c -e "show processlist" >/tmp/mysql_pro.log 2>/tmp/mysql_log.err
  4. n=`wc -l /tmp/mysql_log.err|awk '{print $1}'`
  5. if [ $n -gt 0 ]
  6. then
  7. echo "mysql service sth wrong."
  8. else
  9. $Mysql_c -e "show slave status\G" >/tmp/mysql_s.log
  10. n1=`wc -l /tmp/mysql_s.log|awk '{print $1}'`
  11. if [ $n1 -gt 0 ]
  12. then
  13. y1=`grep 'Slave_IO_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'`
  14. y2=`grep 'Slave_SQL_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'`
  15. if [ $y1 == "Yes" ] && [ $y2 == "Yes" ]
  16. then
  17. echo "slave status good."
  18. else
  19. echo "slave down."
  20. fi
  21. fi
  22. fi

【脚本37】带选项的用户脚本

要求如下:

  1. 只支持三个选项 ‘–del’ ‘–add’ –help输入其他选项报错。
  2. 使用‘–add’需要验证用户名是否存在,存在则反馈存在。且不添加。 不存在则创建该用户,切>添加与该用户名相同的密码。并且反馈。
  3. 使用‘–del’ 需要验证用户名是否存在,存在则删除用户及其家目录。不存在则反馈该用户不存>在。
  4. –help 选项反馈出使用方法
  5. 支持以,分隔 一次删除多个或者添加多个用户。
  6. 能用echo $? 检测脚本执行情况 成功删除或者添加为0,报错信息为其他数字。
  7. 能以,分割。一次性添加或者 删除多个用户。 例如 adddel.sh –add user1,user2,user3…….
  8. 不允许存在明显bug。

代码参考:

  1. #!/bin/bash
  2. #written by aming.
  3. if [ $# -eq 0 -o $# -gt 2 ]
  4. then
  5. echo "use $0 --add username or $0 --del username or $0 --help."
  6. exit 1
  7. fi
  8. case $1 in
  9. --add)
  10. n=0
  11. for u in `echo $2|sed 's/,/ /g'`; do
  12. if awk -F: '{print $1}' /etc/passwd |grep -qw "$u"
  13. then
  14. echo "The user $u exist."
  15. else
  16. useradd $u
  17. echo -e "$u\n$u"|passwd $u >/dev/null 2>&1
  18. echo "The user $u added successfully."
  19. n=$[$n+1]
  20. fi
  21. done
  22. if [ $n -eq 0 ]; then
  23. exit 2
  24. fi
  25. ;;
  26. --del)
  27. n=0
  28. for u in `echo $2|sed 's/,/ /g'`; do
  29. if awk -F: '{print $1}' /etc/passwd|grep -qw "$u"
  30. then
  31. userdel -r $u
  32. echo "The user $u deleted successfully."
  33. n=$[$n+1]
  34. else
  35. echo "The user $u not exist."
  36. fi
  37. done
  38. if [ $n -eq 0 ]; then
  39. exit 3
  40. fi
  41. ;;
  42. --help)
  43. echo -e "--add can add user,and the passwd is the same as username.
  44. It can add multiuser such as --add user1,user2,user3..."
  45. echo "--del cat delete user.It can delete user such as --del user1,user2,user3..."
  46. ;;
  47. *)
  48. echo "use $0 --add username or $0 --del username or $0 --help."
  49. exit 1
  50. ;;
  51. esac

【脚本38】被3整除

写一个脚本: 计算100以内所有能被3整除的正整数的和

代码参考:

  1. #!/bin/bash
  2. sum=0
  3. for i in {1..100};do
  4. if [ $[$i%3] -eq 0 ];then
  5. sum=$[$i+$sum]
  6. fi
  7. done
  8. echo "sum:$sum"

【脚本39】脚本传参

使用传参的方法写个脚本,实现加减乘除的功能。例如: sh a.sh 1 2,这样会分别计算加、减、乘、除的结果。

要求:

  1. 脚本需判断提供的两个数字必须为整数
  2. 当做减法或者除法时,需要判断哪个数字大
  3. 减法时需要用大的数字减小的数字
  4. 除法时需要用大的数字除以小的数字,并且结果需要保留两个小数点。

参考代码:

  1. #!/bin/bash
  2. if [ $# -ne 2 ]
  3. then
  4. echo "The number of parameter is not 2, Please useage: ./$0 1 2"
  5. exit 1
  6. fi
  7. is_int()
  8. {
  9. if echo "$1"|grep -q '[^0-9]'
  10. then
  11. echo "$1 is not integer number."
  12. exit 1
  13. fi
  14. }
  15. max()
  16. {
  17. if [ $1 -ge $2 ]
  18. then
  19. echo $1
  20. else
  21. echo $2
  22. fi
  23. }
  24. min()
  25. {
  26. if [ $1 -lt $2 ]
  27. then
  28. echo $1
  29. else
  30. echo $2
  31. fi
  32. }
  33. sum()
  34. {
  35. echo "$1 + $2 = $[$1+$2]"
  36. }
  37. minus()
  38. {
  39. big=`max $1 $2`
  40. small=`min $1 $2`
  41. echo "$big - $small = $[$big-$small]"
  42. }
  43. mult()
  44. {
  45. echo "$1 * $2 = $[$1*$2]"
  46. }
  47. div()
  48. {
  49. big=`max $1 $2`
  50. small=`min $1 $2`
  51. d=`echo "scale =2; $big / $small"|bc`
  52. echo "$big / $small = $d"
  53. }
  54. is_int $1
  55. is_int $2
  56. sum $1 $2
  57. minus $1 $2
  58. mult $1 $2
  59. div $1 $2

【脚本40】用户交互脚本

写一个脚本,执行后,打印一行提示“Please input a number:”,要求用户输入数值,然后打印出该数值,然后再次要求用户输入数值。直到用户输入”end”停止。

代码参考:

  1. #!/bin/bash
  2. while :
  3. do
  4. read -p "Please input a number:(end for exit) " n
  5. num=` echo $n |sed -r 's/[0-9]//g'|wc -c `
  6. if [ $n == "end" ]
  7. then
  8. exit
  9. elif [ $num -ne 1 ]
  10. then
  11. echo "what you input is not a number!Try again!"
  12. else
  13. echo "your input number is: $n"
  14. fi
  15. done

【脚本41】获取ip

提示用户输入网卡的名字,然后我们用脚本输出网卡的ip。 看似简单,但是需要考虑多个方面,比如我们输入的不符合网卡名字的规范,怎么应对。名字符合规范,但是根本就没有这个网卡有怎么应对。

代码参考:

  1. #!/bin/bash
  2. while :
  3. do
  4. read -p "请输入网卡名: " e
  5. e1=`echo "$e" | sed 's/[-0-9]//g'`
  6. e2=`echo "$e" | sed 's/[a-zA-Z]//g'`
  7. if [ -z $e ]
  8. then
  9. echo "你没有输入任何东西"
  10. continue
  11. elif [ -z $e1 ]
  12. then
  13. echo "不要输入纯数字在centos中网卡名是以eth开头后面加数字"
  14. continue
  15. elif [ -z $e2 ]
  16. then
  17. echo "不要输入纯字母在centos中网卡名是以eth开头后面加数字"
  18. continue
  19. else
  20. break
  21. fi
  22. done
  23. ip() {
  24. ifconfig | grep -A1 "$1 " |tail -1 | awk '{print $2}' | awk -F ":" '{print $2}'
  25. }
  26. myip=`ip $e`
  27. if [ -z $myip ]
  28. then
  29. echo "抱歉,没有这个网卡。"
  30. else
  31. echo "你的网卡IP地址是$myip"
  32. fi

【脚本42】列出子目录

脚本的功能:
脚本可以带参数也可以不带,参数可以有多个,每个参数必须是一个目录,脚本检查参数个数,若等于0,则列出当前目录本身;否则,显示每个参数包含的子目录。

参考代码:

  1. #!/bin/bash
  2. if [ $# == 0 ]
  3. then
  4. ls -ld `pwd`
  5. else
  6. for i in `seq 1 $#`
  7. do
  8. a=$i
  9. echo "ls ${!a}"
  10. ls -l ${!a} |grep '^d'
  11. done
  12. fi

标注:

你可能会对${!a}有疑问,这里是一个特殊用法,在shell中,$1为第一个参数,$2为第二个参数,以此类推,那么这里的数字要是一个变量如何表示呢?比如n=3,我想取第三个参数,能否写成 $$n? shell中是不支持的,那怎么办? 就用脚本中的这种方法:  a=$n, echo ${!a}

【脚本43】下载文件

创建一个函数,能接受两个参数:

  1. 第一个参数为URL,即可下载的文件;第二个参数为目录,即下载后保存的位置;
  2. 如果用户给的目录不存在,则提示用户是否创建;如果创建就继续执行,否则,函数返回一个51的错误值给调用脚本;
  3. 如果给的目录存在,则下载文件;下载命令执行结束后测试文件下载成功与否;如果成功,则>返回0给调用脚本,否则,返回52给调用脚本;

提示,在函数中返回错误值给调用脚本,使用return

参考代码:

  1. #!/bin/bash
  2. if [ ! -d $2 ]
  3. then
  4. echo "please make directory"
  5. exit 51
  6. fi
  7. cd $2
  8. wget $1
  9. n=`echo $?`
  10. if [ $n -eq 0 ];then
  11. exit 0
  12. else
  13. exit 52
  14. fi

【脚本44】猜数字

写一个猜数字脚本,当用户输入的数字和预设数字(随机生成一个小于100的数字)一样时,直接退出,否则让用户一直输入,并且提示用户的数字比预设数字大或者小。

参考代码:

  1. #!/bin/bash
  2. m=`echo $RANDOM`
  3. n1=$[$m%100]
  4. while :
  5. do
  6. read -p "Please input a number: " n
  7. if [ $n == $n1 ]
  8. then
  9. break
  10. elif [ $n -gt $n1 ]
  11. then
  12. echo "bigger"
  13. continue
  14. else
  15. echo "smaller"
  16. continue
  17. fi
  18. done
  19. echo "You are right."

【脚本45】抽签脚本

1、写一个脚本执行后,输入名字,产生随机数01-99之间的数字。
2、如果相同的名字重复输入,抓到的数字还是第一次抓取的结果,
3、前面已经抓到的数字,下次不能在出现相同数字。
4、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出
继续等待别的学生输入。

参考代码:

  1. while :
  2. do
  3. read -p "Please input a name:" name
  4. if [ -f /work/test/1.log ];then
  5. bb=`cat /work/test/1.log | awk -F: '{print $1}' | grep "$name"`
  6. if [ "$bb" != "$name" ];then #名字不重复情况下
  7. aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
  8. while :
  9. do
  10. dd=`cat /work/test/1.log | awk -F: '{print $2}' | grep "$aa"`
  11. if [ "$aa" == "$dd" ];then #数字已经存在情况下
  12. echo "数字已存在."
  13. aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
  14. else
  15. break
  16. fi
  17. done
  18. echo "$name:$aa" | tee -a /work/test/1.log
  19. else
  20. aa=`cat /work/test/1.log | grep "$name" | awk -F: '{print $2}'` #名字重复
  21. echo $aa
  22. echo "重复名字."
  23. fi
  24. else
  25. aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`
  26. echo "$name:$aa" | tee -a /work/test/1.log
  27. fi
  28. done

【脚本46】打印只有一个数字的行

如题,把一个文本文档中只有一个数字的行给打印出来。

参考代码:

  1. #!/bin/bash
  2. f=/etc/passwd
  3. line=`wc -l $f|awk '{print $1}'`
  4. for l in `seq 1 $line`; do
  5. n=`sed -n "$l"p $f|grep -o '[0-9]'|wc -l`;
  6. if [ $n -eq 1 ]; then
  7. sed -n "$l"p $f
  8. fi
  9. done

【脚本47】日志归档

类似于日志切割,系统有个logrotate程序,可以完成归档。但现在我们要自己写一个shell脚本实现归档。

举例: 假如服务的输出日志是1.log,我要求每天归档一个,1.log第二天就变成1.log.1,第三天1.log.2, 第四天 1.log.3 一直到1.log.5

参考答案:

  1. #!/bin/bash
  2. function e_df()
  3. {
  4. [ -f $1 ] && rm -f $1
  5. }
  6. for i in `seq 5 -1 2`
  7. do
  8. i2=$[$i-1]
  9. e_df /data/1.log.$i
  10. if [ -f /data/1.log.$i2 ]
  11. then
  12. mv /data/1.log.$i2 /data/1.log.$i
  13. fi
  14. done
  15. e_df /data/1.log.1
  16. mv /data/1.log /data/1.log.1

【脚本48】找出活动ip

写一个shell脚本,把192.168.0.0/24网段在线的ip列出来。
思路: for循环, 0.1 — 0.254 依次去ping,能通说明在线。

参考代码:

  1. #!/bin/bash
  2. ips="192.168.1."
  3. for i in `seq 1 254`
  4. do
  5. ping -c 2 $ips$i >/dev/null 2>/dev/null
  6. if [ $? == 0 ]
  7. then
  8. echo "echo $ips$i is online"
  9. else
  10. echo "echo $ips$i is not online"
  11. fi
  12. done

【脚本49】检查错误

写一个shell脚本,检查指定的shell脚本是否有语法错误,若有错误,首先显示错误信息,然后提示用户输入q或者Q退出脚本,输入其他内容则直接用vim打开该shell脚本。

提醒: 检查shell脚本有没有语法错误的命令是 sh -n xxx.sh

参考代码:

  1. #!/bin/bash
  2. sh -n $1 2>/tmp/err
  3. if [ $? -eq "0" ]
  4. then
  5. echo "The script is OK."
  6. else
  7. cat /tmp/err
  8. read -p "Please inpupt Q/q to exit, or others to edit it by vim. " n
  9. if [ -z $n ]
  10. then
  11. vim $1
  12. exit
  13. fi
  14. if [ $n == "q" -o $n == "Q" ]
  15. then
  16. exit
  17. else
  18. vim $1
  19. exit
  20. fi
  21. fi

【脚本50】格式化输出

输入一串随机数字,然后按千分位输出。

比如输入数字串为“123456789”,输出为123,456,789

代码参考:

  1. #!/bin/bash
  2. read -p "输入一串数字:" num
  3. v=`echo $num|sed 's/[0-9]//g'`
  4. if [ -n "$v" ]
  5. then
  6. echo "请输入纯数字."
  7. exit
  8. fi
  9. length=${#num}
  10. len=0
  11. sum=''
  12. for i in $(seq 1 $length)
  13. do
  14. len=$[$len+1]
  15. if [[ $len == 3 ]]
  16. then
  17. sum=','${num:$[0-$i]:1}$sum
  18. len=0
  19. else
  20. sum=${num:$[0-$i]:1}$sum
  21. fi
  22. done
  23. if [[ -n $(echo $sum | grep '^,' ) ]]
  24. then
  25. echo ${sum:1}
  26. else
  27. echo $sum
  28. fi

上面这个实现比较复杂,下面再来一个sed的:

  1. #!/bin/bash
  2. read -p "输入一串数字:" num
  3. v=`echo $num|sed 's/[0-9]//g'`
  4. if [ -n "$v" ]
  5. then
  6. echo "请输入纯数字."
  7. exit
  8. fi
  9. echo $num|sed -r '{:number;s/([0-9]+)([0-9]{3})/\1,\2/;t number}'

【脚本51】

1 编写一个名为iffile程序,它执行时判断/bin目录下date文件是否存在?

参考代码:

  1. #!/bin/bash
  2. if [ -f /bin/date ]
  3. then
  4. echo "/bin/date file exist."
  5. else
  6. echo "/bin/date not exist."
  7. fi

2 编写一个名为greet的问候程序,它执行时能根据系统当前的时间向用户输出问候信息。设从半夜到中午为早晨,中午到下午六点为下午,下午六点到半夜为晚上。

参考代码:

  1. #!/bin/bash
  2. h=`date +%H`
  3. if [ $h -ge 0 ] && [ $h -lt 12 ]
  4. then
  5. echo "Good morning."
  6. elif [ $h -ge 12 ] && [ $h -lt 18 ]
  7. then
  8. echo "Good afternoon."
  9. else
  10. echo "Good evening."
  11. fi

【脚本52】判断用户登录

1 编写一个名为ifuser的程序,它执行时带用户名作为命令行参数,判断该用户是否已经在系统中登录,并给出相关信息。

参考代码:

  1. #!/bin/bash
  2. read -p "Please input the username: " user
  3. if who | grep -qw $user
  4. then
  5. echo $user is online.
  6. else
  7. echo $user not online.
  8. fi

2 编写一个名为menu的程序,实现简单的弹出式菜单功能,用户能根据显示的菜单项从键盘选择执行对应的命令。

参考代码:

  1. #!/bin/bash
  2. function message()
  3. {
  4. echo "0. w"
  5. echo "1. ls"
  6. echo "2.quit"
  7. read -p "Please input parameter: " Par
  8. }
  9. message
  10. while [ $Par -ne '2' ] ; do
  11. case $Par in
  12. 0)
  13. w
  14. ;;
  15. 1)
  16. ls
  17. ;;
  18. 2)
  19. exit
  20. ;;
  21. *)
  22. echo "Unkown command"
  23. ;;
  24. esac
  25. message
  26. done

【脚本53】更改后缀名

1 编写一个名为chname的程序,将当前目录下所有的.txt文件更名为.doc文件。

参考代码:

  1. #!/bin/bash
  2. find . -type f -name "*.txt" > /tmp/txt.list
  3. for f in `cat /tmp/txt.list`
  4. do
  5. n=`echo $f|sed -r 's/(.*)\.txt/\1/'`
  6. echo "mv $f $n.doc"
  7. done

2 编写一个名为chuser的程序,执行中每隔5分钟检查指定的用户是否登录系统,用户名从命令行输入;如果指定的用户已经登录,则显示相关信息。

参考代码:

  1. #!/bin/bash
  2. read -p "Please input the username: " user
  3. while :
  4. do
  5. if who | grep -qw $user
  6. then
  7. echo $user login.
  8. else
  9. echo $user not login.
  10. fi
  11. sleep 300
  12. done

【脚本54】判断pid是否一致

先普及一小段知识,我们用ps aux可以查看到进程的PID,而每个PID都会在/proc内产生。如果查看到的pid而proc内是没有的,则是进程被人修改了,这就代表你的系统很有可能已经被***过了。

请大家用上面知识编写一个shell,定期检查下自己的系统是否被人***过。

参考代码:

  1. #!/bin/bash
  2. ps aux|awk '/[0-9]/ {print $2}'|while read pid
  3. do
  4. result=`find /proc/ -maxdepth 1 -type d -name "$pid"`
  5. if [ -z $result ]; then
  6. echo "$pid abnormal!"
  7. fi
  8. done

【脚本55】一列变三行

比如1.txt内容:

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7

处理后应该是:

  1. 1 2 3
  2. 4 5 6
  3. 7

可使用sed命令完成:

sed 'N;N;s/\n/ /g' 1.txt

【脚本56】shell的getops

写一个getinterface.sh 脚本可以接受选项[i,I],完成下面任务:

  1. 使用一下形式:getinterface.sh [-i interface | -I ip]
  2. 当用户使用-i选项时,显示指定网卡的IP地址;当用户使用-I选项时,显示其指定ip所属的网卡。
    • 例:sh getinterface.sh -i eth0
    • sh getinterface.sh -I 192.168.0.1
  3. 当用户使用除[-i | -I]选项时,显示[-i interface | -I ip]此信息。
  4. 当用户指定信息不符合时,显示错误。(比如指定的eth0没有,而是eth1时)

参考代码:

  1. #!/bin/bash
  2. ip add |awk -F ":" '$1 ~ /^[1-9]/ {print $2}'|sed 's/ //g' > /tmp/eths.txt
  3. [ -f /tmp/eth_ip.log ] && rm -f /tmp/eth_ip.log
  4. for eth in `cat /tmp/eths.txt`
  5. do
  6. ip=`ip add |grep -A2 ": $eth" |grep inet |awk '{print $2}' |cut -d '/' -f 1`
  7. echo "$eth:$ip" >> /tmp/eth_ip.log
  8. done
  9. useage()
  10. {
  11. echo "Please useage: $0 -i 网卡名字 or $0 -I ip地址"
  12. }
  13. wrong_eth()
  14. {
  15. if ! awk -F ':' '{print $1}' /tmp/eth_ip.log | grep -qw "^$1$"
  16. then
  17. echo "请指定正确的网卡名字"
  18. exit
  19. fi
  20. }
  21. wrong_ip()
  22. {
  23. if ! awk -F ':' '{print $2}' /tmp/eth_ip.log | grep -qw "^$1$"
  24. then
  25. echo "请指定正确的ip地址"
  26. exit
  27. fi
  28. }
  29. if [ $# -ne 2 ]
  30. then
  31. useage
  32. exit
  33. fi
  34. case $1 in
  35. -i)
  36. wrong_eth $2
  37. grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $2}'
  38. ;;
  39. -I)
  40. wrong_ip $2
  41. grep -w $2 /tmp/eth_ip.log |awk -F ':' '{print $1}'
  42. ;;
  43. *)
  44. useage
  45. exit
  46. esac

【脚本57】3位随机数字

写一个脚本产生随机3位的数字,并且可以根据用户的输入参数来判断输出几组。 比如,脚本名字为 number3.sh。
执行方法:
bash number3.sh
直接产生一组3位数字。
bash number3.sh 10
插上10组3位数字。

思路: 可以使用echo $RANDOM获取一个随机数字,然后再除以10,取余获取0-9随机数字,三次运算获得一组。

参考代码:

  1. #!/bin/bash
  2. get_a_num() {
  3. n=$[$RANDOM%10]
  4. echo $n
  5. }
  6. get_numbers() {
  7. for i in 1 2 3; do
  8. a[$i]=`get_a_num`
  9. done
  10. echo ${a[@]}
  11. }
  12. if [ -n "$1" ]; then
  13. m=`echo $1|sed 's/[0-9]//g'`
  14. if [ -n "$m" ]; then
  15. echo "Useage bash $0 n, n is a number, example: bash $0 5"
  16. exit
  17. else
  18. for i in `seq 1 $1`
  19. do
  20. get_numbers
  21. done
  22. fi
  23. else
  24. get_numbers
  25. fi

【脚本58】检查服务

先判断是否安装http和mysql,没有安装进行安装,安装了检查是否启动服务,若没有启动则需要启动服务。

说明:操作系统为centos6,httpd和mysql全部为rpm包安装。

参考代码:

  1. #!/bin/bash
  2. if_install()
  3. {
  4. n=`rpm -qa|grep -cw "$1"`
  5. if [ $n -eq 0 ]
  6. then
  7. echo "$1 not install."
  8. yum install -y $1
  9. else
  10. echo "$1 installed."
  11. fi
  12. }
  13. if_install httpd
  14. if_install mysql-server
  15. chk_ser()
  16. {
  17. p_n=`ps -C "$1" --no-heading |wc -l`
  18. if [ $p_n -eq 0 ]
  19. then
  20. echo "$1 not start."
  21. /etc/init.d/$1 start
  22. else
  23. echo "$1 started."
  24. fi
  25. }
  26. chk_httpd
  27. chk_mysqld

【脚本59】判断日期是否合法

用shell脚本判断输入的日期是否合法。就是判断日期是都是真实的日期,比如20170110就是合法日期,20171332就不合法

参考代码:

  1. #!/bin/bash
  2. #check date
  3. if [ $# -ne 1 ] || [ ${#1} -ne 8 ]
  4. then
  5. echo "Usage: bash $0 yyyymmdd"
  6. exit 1
  7. fi
  8. datem=$1
  9. year=${datem:0:4}
  10. month=${datem:4:2}
  11. day=${datem:6:2}
  12. if echo $day|grep -q '^0'
  13. then
  14. day=`echo $day |sed 's/^0//'`
  15. fi
  16. if cal $month $year >/dev/null 2>/dev/null
  17. then
  18. daym=`cal $month $year|egrep -v "$year|Su"|grep -w "$day"`
  19. if [ "$daym" != "" ]
  20. then
  21. echo ok
  22. else
  23. echo "Error: Please input a wright date."
  24. exit 1
  25. fi
  26. else
  27. echo "Error: Please input a wright date."
  28. exit 1
  29. fi

【脚本60】监控网卡

1.每10分钟检测一次指定网卡的流量
2.如果流量为0,则重启网卡

参考代码:

  1. #!/bin/bash
  2. LANG=en
  3. n1=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $5}'|sed 's/\.//g'`
  4. n2=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $6}'|sed 's/\.//g'`
  5. if [ $n1 == "000" ] && [ $n2 == "000" ]
  6. then
  7. ifdown eth0
  8. ifup eth0
  9. fi

然后写个cron,10分钟执行一次


【脚本61】监控web可用性

写一个shell脚本,通过curl -I 返回的状态码来判定所访问的网站是否正常。比如,当状态码为200时,才算正常。

参考代码:

  1. #/bin/bash
  2. url="http://www.apelearn.com/index.php"
  3. sta=`curl -I $url 2>/dev/null |head -1 |awk '{print $2}'`
  4. if [ $sta != "200" ]
  5. then
  6. python /usr/local/sbin/mail.py xxx@qq.com "$url down." "$url down"
  7. fi

【脚本62】文件打包

需求:将用户家目录(考虑到执行脚本的用户可能是普通用户也可能是root)下面小于5KB的文件打包成tar.gz的压缩包,并以当前日期为文件名前缀,例如今天打包的文件为2017-09-15.tar.gz。

参考代码:

  1. #!/bin/bash
  2. t=`date +%F`
  3. cd $HOME
  4. tar czf $t.tar.gz `find . -type f -size -5k`

【脚本63】端口解封

一个小伙伴提到一个问题,他不小心用iptables规则把sshd端口22给封掉了,结果不能远程登陆,要想解决这问题,还要去机房,登陆真机去删除这规则。 问题来了,要写个监控脚本,监控iptables规则是否封掉了22端口,如果封掉了,给打开。 写好脚本,放到任务计划里,每分钟执行一次。

参考代码:

  1. #!/bin/bash
  2. # check sshd port drop
  3. /sbin/iptables -nvL --line-number|grep "dpt:22"|awk -F ' ' '{print $4}' > /tmp/drop.txt
  4. i=`cat /tmp/drop.txt|head -n 1|egrep -iE "DROP|REJECT"|wc -l`
  5. if [ $i -gt 0 ]
  6. then
  7. /sbin/iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT
  8. fi

【脚本64】统计分析日志

已知nginx访问的日志文件在/usr/local/nginx/logs/access.log内

请统计下早上10点到12点 来访ip最多的是哪个?

日志样例:

  1. 111.199.186.68 – [15/Sep/2017:09:58:37 +0800] “//plugin.php?id=security:job” 200 “POST //plugin.php?id=security:job HTTP/1.1″”http://a.lishiming.net/forum.php?mod=viewthread&tid=11338&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline” “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36” “0.516”
  2. 203.208.60.208 – [15/Sep/2017:09:58:46 +0800] “/misc.php?mod=patch&action=ipnotice&_r=0.05560809863330207&inajax=1&ajaxtarget=ip_notice” 200 “GET /misc.php?mod=patch&action=ipnotice&_r=0.05560809863330207&inajax=1&ajaxtarget=ip_notice HTTP/1.1″”http://a.lishiming.net/forum.php?mod=forumdisplay&fid=65&filter=author&orderby=dateline” “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3141.7 Safari/537.36” “0.065”

实现这个需求使用如下命令即可:

grep '15/Sep/2017:1[0-2]:[0-5][0-9]:' /usr/local/nginx/logs/access.log|awk '{print $1}'|sort -n|uniq -c |sort -n|tail -n1

【脚本65】打印数字

写一个shell脚本。提示你输入一个暂停的数字,然后从1打印到该数字。然后询问是否继续。继续的话在输入个在数字 接着打印。不继续退出。

例:如果输入的是5,打印1 2 3 4 5 然后继续 输入15 然后打印 6 7 …14 15 依此类推。

参考代码:

  1. #!/bin/bash
  2. read -p "请输入您想要暂停的数字:" number_1
  3. for i in `seq 1 $number_1`;
  4. do
  5. echo $i
  6. done
  7. read -p "是否继续输入数字?" a
  8. if [ $a == "yes" ];then
  9. read -p "请继续输入您想要暂停的数字:" number_2
  10. number_3=$[$number_1+1]
  11. if [ $number_2 -gt $number_1 ];then
  12. for h in `seq $number_3 $number_2`;
  13. do
  14. echo $h
  15. done
  16. else
  17. echo "输入数字错误,请输入大于的数字!"
  18. fi
  19. else
  20. exit
  21. fi

【脚本66】给文档增加内容

在文本文档1.txt第5行(假设文件行数大于5)后面增加如下内容:

  1. # This is a test file.
  2. # Test insert line into this file.

参考命令:

sed -i "5a # This is a test file.\n# Test insert line into this file." 1.txt

【脚本67】备份etc下面文件

设计一个shell程序,在每月第一天备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式”yymmdd_etc.tar.gz”,yy为年,mm为月,dd为日。

参考代码:

  1. #!/bin/sh
  2. if [ ! -d /root/bak ]
  3. then
  4. mkdir /root/bak
  5. fi
  6. prefix=`date +%y%m%d`
  7. d=`date +%d`
  8. if [ $d == "01" ]
  9. then
  10. cd /etc/
  11. tar czf /root/bak/$prefix_etc.tar.gz ./
  12. fi

【脚本68】计算单词重复次数

将文件内所有的单词的重复次数计算出来,只需要列出重复次数最多的10个单词。

假设文档名字叫做a.txt,使用如下命令即可:

sed 's/[^a-zA-Z]/ /g' a.txt|xargs -n1 |sort |uniq -c |sort -nr |head

【脚本69】成员分组

需求是,把所有的成员平均得分成若干个小组。这里,我会提供一个人员列表,比如成员有50人,需要分成7个小组,要求随机性,每次和每次分组的结构应该不一致。

假设成员列表文件为members.txt

参考代码:

  1. #!/bin/bash
  2. f=members.txt
  3. n=`wc -l $f|awk '{print $1}'`
  4. get_n()
  5. {
  6. l=`echo $1|wc -c`
  7. n1=$RANDOM
  8. n2=$[$n1+$l]
  9. g_id=$[$n1%7]
  10. if [ $g_id -eq 0 ]
  11. then
  12. g_id=7
  13. fi
  14. echo $g_id
  15. }
  16. for i in `seq 1 7`
  17. do
  18. [ -f n_$i.txt ] && rm -f n_$i.txt
  19. done
  20. for i in `seq 1 $n`
  21. do
  22. name=`sed -n "$i"p $f`
  23. g=`get_n $name`
  24. echo $name >> n_$g.txt
  25. done
  26. nu(){
  27. wc -l $1|awk '{print $1}'
  28. }
  29. max(){
  30. ma=0
  31. for i in `seq 1 7`
  32. do
  33. n=`nu n_$i.txt`
  34. if [ $n -gt $ma ]
  35. then
  36. ma=$n
  37. fi
  38. done
  39. echo $ma
  40. }
  41. min(){
  42. mi=50
  43. for i in `seq 1 7`
  44. do
  45. n=`nu n_$i.txt`
  46. if [ $n -lt $mi ]
  47. then
  48. mi=$n
  49. fi
  50. done
  51. echo $mi
  52. }
  53. ini_min=1
  54. while [ $ini_min -le 7 ]
  55. do
  56. m1=`max`
  57. m2=`min`
  58. ini_min=m2
  59. for i in `seq 1 7`
  60. do
  61. n=`nu n_$i.txt`
  62. if [ $n -eq $m1 ]
  63. then
  64. f1=n_$i.txt
  65. elif [ $n -eq $m2 ]
  66. then
  67. f2=n_$i.txt
  68. fi
  69. done
  70. name=`tail -n1 $f1`
  71. echo $name >> $f2
  72. sed -i "/$name/d" $f1
  73. ini_min=$[$ini_min+1]
  74. done
  75. for i in `seq 1 7`
  76. do
  77. echo "$i 组成员有:"
  78. cat n_$i.txt
  79. echo
  80. done

【脚本70】shell中的小数

有一组式子如下:

  1. a=0.5
  2. b=3
  3. c=a*b

求c的值,参考代码:

  1. #!/bin/bash
  2. a=0.5
  3. b=3
  4. c=`echo "scale=1;$a*$b"|bc`
  5. echo $c

【脚本71】a.txt有b.txt没有

有两个文件a.txt和b.txt,需求是,把a.txt中有的并且b.txt中没有的行找出来,并写入到c.txt,然后计算c.txt文件的行数。

参考代码:

  1. #!/bin/bash
  2. n=`wc -l a.txt|awk '{print $1}'`
  3. [ -f c.txt ] && rm -f c.txt
  4. for i in `seq 1 $n`
  5. do
  6. l=`sed -n "$i"p a.txt`
  7. if ! grep -q "^$l$" b.txt
  8. then
  9. echo $l >>c.txt
  10. fi
  11. done
  12. wc -l c.txt
  13. 或者用grep实现
  14. grep -vwf b.txt a.txt > c.txt; wc -l c.txt

【脚本72】杀死进程

把当前用户下所有进程名字中含有”java”的进程关闭。

参考答案:

ps -u $USER |awk '$NF ~ /java/ {print $1}'|xargs kill

【脚本73】备份数据表

用shell实现,以并发进程的形式将mysql数据库所有的表备份到当前目录,并把所有的表压缩到一个压缩包文件里。

假设数据库名字为mydb,用户名为zero,密码为passwd。

提示: 在shell中加上&可以将命令丢到后台,从而可以同时执行多条命令达到并发的效果。

参考代码:

  1. #!/bin/bash
  2. pre=`date +%F`
  3. for d in `mysql -uaming -ppasswd mydb -e "show tables"|grep -v 'Tables_in_'`
  4. do
  5. mysqldump -uaming -ppasswd mydb $d > $d.sql &
  6. done
  7. tar czf $pre.tar.gz *.sql
  8. rm -f *.sql

【脚本74】监控节点

一个网站,使用了cdn,全国各地有几十个节点。需要你写一个shell脚本来监控各个节点是否正常。

假如:

  1. 监控的url为www.xxx.com/index.php
  2. 源站ip为88.88.88.88

参考代码:

  1. #!/bin/bash
  2. url="www.xxx.com/index.php"
  3. s_ip="88.88.88.88"
  4. curl -x $s_ip:80 $url > /tmp/source.html 2>/dev/null
  5. for ip in `cat /tmp/ip.txt`
  6. do
  7. curl -x $ip:80 $url 2>/dev/null >/tmp/$ip.html
  8. [ -f /tmp/$ip.diff ] && rm -f /tmp/$ip.diff
  9. touch /tmp/$ip.diff
  10. diff /tmp/source.html /tmp/$ip.html > /tmp/$ip.diff 2>/dev/null
  11. n=`wc -l /tmp/$ip.diff|awk '{print $1}'`
  12. if [ $n -lt 0 ]
  13. then
  14. echo "node $ip sth wrong."
  15. fi
  16. done

【脚本75】破解字符串

已知下面的字符串是通过RANDOM随机数变量md5sum|cut-c 1-8截取后的结果,请破解这些字符串对应的md5sum前的RANDOM对应数字?

  1. 21029299
  2. 00205d1c
  3. a3da1677
  4. 1f6d12dd
  5. 890684ba

解题思路:通过每次传递一个参数的方式,来实现依次破解,$RANDOM的范围为0-32767。

参考代码:

  1. #!/bin/bash
  2. for n in {0..32767}
  3. do
  4. MD5=`echo $n | md5sum | cut -c 1-8`
  5. if [ "$MD5" == "$1" ];then
  6. echo "$n $1 "
  7. break
  8. fi
  9. done

【脚本76】判断cpu厂商

写一个脚本:

  1. 判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id一行中。
  2. 如果其生产商为AuthenticAMD,就显示其为AMD公司;
  3. 如果其生产商为GenuineIntel,就显示其为Intel公司;
  4. 否则,就说其为非主流公司。

参考代码:

  1. #!/bin/bash
  2. m=`cat /proc/cpuinfo |grep vendor_id|awk -F":" '{print $2}'|tail -1`
  3. if [ $m == "GenuineIntel" ]
  4. then
  5. echo "cpu is 英特尔"
  6. elif [ $m == "AuthenticAMD" ]
  7. then
  8. echo "cpu is AMD"
  9. else
  10. echo "cpu is 非主流"
  11. fi

【脚本77】监控cpu使用率

用shell写一个监控服务器cpu使用率的监控脚本。

思路:用top -bn1 命令,取当前空闲cpu百份比值(只取整数部分),然后用100去剑这个数值。

参考代码:

  1. #!/bin/bash
  2. while :
  3. do
  4. idle=`top -bn1 |sed -n '3p' |awk '{print $5}'|cut -d . -f1`
  5. use=$[100-$idle]
  6. if [ $use -gt 90 ]
  7. then
  8. echo "cpu use percent too high."
  9. #发邮件省略
  10. fi
  11. sleep 10
  12. done

【脚本78】获取子进程

说明:本shell题目是一个网友在公众号中提问的,正好利用这个每日习题的机会拿出来让大家一起做一做。

给出一个进程PID,打印出该进程下面的子进程以及子进程下面的所有子进程。(只需要考虑子进程的子进程,再往深层次则不考虑)

参考代码:

  1. #!/bin/bash
  2. read -p "please input a pid number: " p
  3. ps -elf > /tmp/ps.log
  4. is_ppid(){
  5. awk '{print $5}' /tmp/ps.log > /tmp/ps1.log
  6. if ! grep -qw "$1" /tmp/ps1.log
  7. then
  8. echo "PID $1 不是系统进程号,或者它不是父进程"
  9. return 1
  10. fi
  11. }
  12. is_ppid $p
  13. if [ $? -eq "1" ]
  14. then
  15. exit
  16. fi
  17. print_cpid(){
  18. p=$1
  19. awk -v p1=$p '$5 == p1 {print $4}' /tmp/ps.log |sort -n |uniq >/tmp/p1.log
  20. n=`wc -l /tmp/p1.log|awk '{print $1}'`
  21. if [ $n -ne 0 ]
  22. then
  23. echo "PID $p 子进程 pid 如下:"
  24. cat /tmp/p1.log
  25. else
  26. echo "PID $p 没有子进程"
  27. fi
  28. }
  29. print_cpid $p
  30. for cp in `cat /tmp/p1.log`
  31. do
  32. print_cpid $cp
  33. done

另外,一条命令查询的方法是:

pstree -p pid

【脚本79】自动添加项目

需求背景:
服务器上,跑的lamp环境,上面有很多客户的项目,每个项目就是一个网站。 由于客户在不断增加,每次增加一个客户,就需要配置相应的mysql、ftp以及httpd. 这种工作是重复性非常强的,所以用脚本实现非常合适。

mysql增加的是对应客户项目的数据库、用户、密码,ftp增加的是对应项目的用户、密码(使用vsftpd,虚拟用户模式),httpd就是要增加虚拟主机配置段。

参考代码:

  1. #!/bin/bash
  2. webdir=/home/wwwroot
  3. ftpudir=/etc/vsftpd/vuuser
  4. mysqlc="/usr/bin/mysql -uroot -xxxxxx"
  5. httpd_config_f="/usr/local/apache2/conf/extra/httpd-vhosts.conf"
  6. add_mysql_user()
  7. {
  8. mysql_p=`mkpasswd -s 0 -l 12`
  9. echo "$pro $mysql_p" >/tmp/$pro.txt
  10. $mysqlc <<EOF
  11. grant all on $p.* to "$pro"@'127.0.0.1' identified by "$mysql_p";
  12. EOF
  13. }
  14. add_ftp_user()
  15. {
  16. ftp_p=`mkpasswd -s 0 -l 12`
  17. echo "$pro" >> /root/login.txt
  18. echo "$ftp_p" >> /root/login.txt
  19. db_load -T -t hash -f /root/login.txt /etc/vsftpd/vsftpd_login.db
  20. cd $ftpudir
  21. cp aaa $pro //这里的aaa是一个文件,是之前的一个项目,可以作为配置模板
  22. sed -i "s/aaa/$pro/" $pro //把里面的aaa改为新的项目名字
  23. /etc/init.d/vsftpd restart
  24. }
  25. config_httpd()
  26. {
  27. mkdir $webdir/$pro
  28. chown vsftpd:vsftpd $webdir/$pro
  29. echo -e "<VirtualHost *:80> \n DocumentRoot "/home/internet/www/$pro/" \n ServerName $dom \n #ServerAlias \n</VirtualHost> " >> $httpd_config_f
  30. /usr/local/apache2/bin/apachectl graceful
  31. }
  32. read -p "input the project name: " pro
  33. read -p "input the domain: " dom
  34. add_mysql_user
  35. add_ftp_user
  36. config_httpd

【脚本80】计算器

用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2

参考代码:

  1. #!/bin/bash
  2. if [ $# -ne 3 ]
  3. then
  4. echo "参数个数不为3"
  5. echo "当使用乘法时,需要加上脱义符号,例如 $0 1 \* 2"
  6. exit 1;
  7. fi
  8. num1=`echo $1|sed 's/[0-9.]//g'` ;
  9. if [ -n "$num1" ]
  10. then
  11. echo "$1 不是数字" ;
  12. exit 1
  13. fi
  14. num3=`echo $3|sed 's/[0-9.]//g'` ;
  15. if [ -n "$num3" ]
  16. then
  17. echo "$3 不是数字" ;
  18. exit 1
  19. fi
  20. case $2 in
  21. +)
  22. echo "scale=2;$1+$3" | bc
  23. ;;
  24. -)
  25. echo "scale=2;$1-$3" | bc
  26. ;;
  27. \*)
  28. echo "scale=2;$1*$3" | bc
  29. ;;
  30. /)
  31. echo "scale=2;$1/$3" | bc
  32. ;;
  33. *)
  34. echo "$2 不是运算符"
  35. ;;
  36. esac

【脚本81】判断没有文件

判断所给目录内哪些二级目录下没有text.txt文件。

有text.txt文件的二级目录,根据文件计算选项中单词数最大的值(选项间以|分割,单词间以空格分隔)。

假如脚本名字为1.sh, 运行脚本的格式为 ./1.sh 123 root,其中123为目录名字,而root为要计算数量的单词。

说明: 这个shell脚本题目出的有点歧义。 原题给的描述不是很清楚,我另外又改了一下需求,依然不是很清晰。在这里我再做一个补充: 对于有test.txt的目录,计算出该test.txt文件里面所给出单词的次数。不用找最大。

参考代码:

  1. #!/bin/bash
  2. if [ $# -ne 2 ]
  3. then
  4. echo "useage $0 dir word"
  5. exit 1
  6. fi
  7. if [ -d $1 ]
  8. then
  9. cd $1
  10. else
  11. echo "$1目录不存在"
  12. exit 1
  13. fi
  14. for f in `ls $1`
  15. do
  16. if [ -d $f ]
  17. then
  18. if [ -f $f/test.txt ]
  19. then
  20. n=`grep -cw "$2" $f/test.txt`
  21. echo "$1/$f/test.txt 里面有$n$2"
  22. else
  23. echo "$1/$f 下面没有test.txt"
  24. fi
  25. fi
  26. done

【脚本82】打印正方形

交互式脚本,根据提示,需要用户输入一个数字作为参数,最终打印出一个正方形。

在这里我提供一个linux下面的特殊字符■,可以直接打印出来。

示例: 如果用户输入数字为5,则最终显示的效果为:

  1. ■ ■ ■ ■ ■
  2. ■ ■ ■ ■ ■
  3. ■ ■ ■ ■ ■
  4. ■ ■ ■ ■ ■
  5. ■ ■ ■ ■ ■

参考代码:

  1. #!/bin/bash
  2. read -p "please input a number:" sum
  3. a=`echo $sum |sed 's/[0-9]//g'`
  4. if [ -n "$a" ]
  5. then
  6. echo "请输入一个纯数字。"
  7. exit 1
  8. fi
  9. for n in `seq $sum`
  10. do
  11. for m in `seq $sum`
  12. do
  13. if [ $m -lt $sum ]
  14. then
  15. echo -n "■ "
  16. else
  17. echo "■"
  18. fi
  19. done
  20. done

【脚本83】问候用户

写一个脚本,依次向/etc/passwd中的每个用户问好,并且说出对方的ID是什么:

Hello,root,your UID is 0.

参考命令:

awk -F ':' '{print "Hello,"$1",your uid is "$3.}' /etc/passwd

【脚本84】按要求处理文本

linux系统 /home目录下有一个文件test.xml,内容如下:

  1. <configuration>
  2. <artifactItems>
  3. <artifactItem>
  4. <groupId>zzz</groupId>
  5. <artifactId>aaa</artifactId>
  6. </artifactItem>
  7. <artifactItem>
  8. <groupId>xxx</groupId>
  9. <artifactId>yyy</artifactId>
  10. </artifactItem>
  11. <!-- </artifactItem><groupId>some groupId</groupId>
  12. <version>1.0.1.2.333.555</version> </artifactItem>-->
  13. </artifactItems>
  14. </configuration>

请写出shell脚本删除文件中的注释部分内容,获取文件中所有artifactItem的内容,并用如下格式逐行输出 artifactItem:groupId:artifactId

分析:这个文件比较特殊,但是却很有规律。注释部分内容其实就是<!– –>中间的内容,所以我们想办法把这些内容删除掉就ok了。而artifactItem的内容,其实就是获取<artifactItem></artifactItem>中间的内容。然后想办法用提到的格式输出即可。

参考代码:

  1. #!/bin/bash
  2. egrep -v '<!--|-->' 1.txt |tee 2.txt //这行就是删除掉注释的行
  3. grep -n 'artifactItem>' 2.txt |awk '{print $1}' |sed 's/://' > /tmp/line_number.txt
  4. n=`wc -l /tmp/line_number.txt|awk '{print $1}'`
  5. get_value(){
  6. sed -n "$1,$2"p 2.txt|awk -F '<' '{print $2}'|awk -F '>' '{print $1,$2}' > /tmp/value.txt
  7. nu=`wc -l /tmp/value.txt|awk '{print $1}'`
  8. for i in `seq 1 $nu`
  9. do
  10. x=`sed -n "$i"p /tmp/value.txt|awk '{print $1}'`
  11. y=`sed -n "$i"p /tmp/value.txt|awk '{print $2}'`
  12. echo artifactItem:$x:$y
  13. done
  14. }
  15. n2=$[$n/2]
  16. for j in `seq 1 $n2`
  17. do
  18. m1=$[$j*2-1]
  19. m2=$[$j*2]
  20. nu1=`sed -n "$m1"p /tmp/line_number.txt`
  21. nu2=`sed -n "$m2"p /tmp/line_number.txt`
  22. nu3=$[$nu1+1]
  23. nu4=$[$nu2-1]
  24. get_value $nu3 $nu4
  25. done

【脚本85】判断函数

请使用条件函数if撰写一个shell函数 函数名为 f_judge,实现以下功能:

  1. 当/home/log 目录存在时 将/home目录下所有tmp开头的文件或目录移/home/log 目录。
  2. 当/home/log目录不存在时,创建该目录,然后退出。

参考代码:

  1. #!/bin/bash
  2. f_judge (){
  3. if [ -d /home/log ]
  4. then
  5. mv /home/tmp* /home/log/
  6. else
  7. mkdir -p /home/log
  8. exit
  9. fi
  10. }

【脚本86】批量杀进程

linux系统中,根目录/root/下有一个文件ip-pwd.ini,内容如下:

  1. 10.111.11.1,root,xyxyxy
  2. 10.111.11.1,root,xzxzxz
  3. 10.111.11.1,root,123456
  4. 10.111.11.1,root,xxxxxx
  5. ……

文件中每一行的格式都为linux服务器的ip,root用户名,root密码,请用一个shell批量将这些服务器中的所有tomcat进程kill掉。

讲解: 有了ip,用户名和密码,剩下的就是登录机器,然后执行命令了。批量登录机器,并执行命令,咱们课程当中有讲过一个expect脚本。所以本题就是需要这个东西来完成。

首先编辑expect脚本 kill_tomcat.expect:

  1. #!/usr/bin/expect
  2. set passwd [lindex $argv 0]
  3. set host [lindex $argv 1]
  4. spawn ssh root@$host
  5. expect {
  6. "yes/no" { send "yes\r"; exp_continue}
  7. "password:" { send "$passwd\r" }
  8. }
  9. expect "]*"
  10. send "killall java\r"
  11. expect "]*"
  12. send "exit\r"

编辑完后需要给这个文件执行权限:

chmod a+x kill_tomcat.expect

然后编辑shell脚本:

  1. #!/bin/bash
  2. n=`wc -l ip-pwd.ini`
  3. for i in `seq 1 $n`
  4. do
  5. ip=`sed -n "$n"p ip-pwd.ini |awk -F ',' '{print $1}'`
  6. pw=`sed -n "$n"p ip-pwd.ini |awk -F ',' '{print $3}'`
  7. ./kill_tomcat.expect $pw $ip
  8. done

【脚本87】处理日志

写一个脚本查找/data/log目录下,最后创建时间是3天前,后缀是*.log的文件,打包后发送至192.168.1.2服务上的/data/log下,并删除原始.log文件,仅保留打包后的文件

参考代码:

  1. #!/bin/bash
  2. find /data/log -name “*.log” -mtime +3 > /tmp/file.list
  3. cd /data/log
  4. tar czvf log.tar.gz `cat /tmp/file.list|xargs`
  5. rsync -a log.tar.gz 192.168.1.2:/data/log # 这一步需要提前做一个免密码登录
  6. for f in `cat /tmp/file.list`
  7. do
  8. rm -f $f
  9. done

【脚本88】处理文本

有如下文本,其中前5行内容为

  1. 1111111:13443253456
  2. 2222222:13211222122
  3. 1111111:13643543544
  4. 3333333:12341243123
  5. 2222222:12123123123

用shell脚本处理后,按下面格式输出:

  1. [1111111]
  2. 13443253456
  3. 13643543544
  4. [2222222]
  5. 13211222122
  6. 12123123123
  7. [3333333]
  8. 12341243123

参考代码:

  1. #! /bin/bash
  2. sort -n filename |awk -F ':' '{print $1}'|uniq >id.txt
  3. for id in `cat id.txt`; do
  4. echo "[$id]"
  5. awk -v id2=$id -F ':' '$1==id2 {print $2}' filename
  6. #另外的方式为: awk -F ':' '$1=="'$id'" {print $2}' filename
  7. done

【脚本89】清理日志

要求:两类机器一共300多台,写个脚本自动清理这两类机器里面的日志文件。在堡垒机批量发布,也要批量发布到crontab里面。

A类机器日志存放路径很统一,B类机器日志存放路径需要用匹配(因为这个目录里除了日志外,还有其他文件,不能删除。匹配的时候可用.log)

A类:/opt/cloud/log/ 删除7天前的
B类: /opt/cloud/instances/ 删除15天前的

要求写在一个脚本里面。不用考虑堡垒机上的操作,只需要写出shell脚本。

参考代码:

  1. #!/bin/bash
  2. dir1=/opt/cloud/instances/
  3. dir2=/opt/cloud/log/
  4. if [ -d $dir1 ];then
  5. find $dir1 -type f -name "*.log" -mtime +15 |xargs rm -f
  6. elif [ -d $dir2 ];then
  7. find $dir2 -type f -mtime +7 |xargs rm -f
  8. fi

【脚本90】

贷款有两种还款的方式:等额本金法和等额本息法

简单说明一下等额本息法与等额本金法的主要区别:

等额本息法的特点是:每月的还款额相同,在月供中“本金与利息”的分配比例中,前半段时期所还的利息比例大、本金比例小,还款期限过半后逐步转为本金比例大、利息比例小。所支出的总利息比等额本金法多,而且贷款期限越长,利息相差越大。

等额本金法的特点是:每月的还款额不同,它是将贷款额按还款的总月数均分(等额本金),再加上上期剩余本金的月利息,形成一个月还款额,所以等额本金法第一个月的还款额最多 ,尔后逐月减少,越还越少。所支出的总利息比等额本息法少。

两种还款方式的比较不是我们今天的讨论范围,我们的任务就是做一个贷款计算器。

其中:等额本息每月还款额的计算公式是:
[贷款本金×月利率×(1+月利率)^还款月数]÷[(1+月利率)^还款月数-1]

参考代码:

  1. #!/bin/bash
  2. read -p "请输入贷款总额(单位:万元):" dkzewy
  3. read -p "请输入贷款年利率(如年利率为6.5%,直接输入6.5):" dknll
  4. read -p "请输入贷款年限(单位:年):" dknx
  5. echo "贷款计算方式:"
  6. echo "1)等额本金计算法"
  7. echo "2)等额本息计算法"
  8. read -p "请选择贷款方式(1|2)" dkfs
  9. dkze=`echo "scale=2;$dkzewy*10000 " | bc -l`
  10. dkll=`echo "scale=6;$dknll/100 " | bc -l`
  11. dkyll=`echo "scale=6;$dkll/12 " | bc -l`
  12. dkqc=$[$dknx*12]
  13. echo "期次 本月还款额 本月利息 未还款额"
  14. debjjsf()
  15. {
  16. yhbj=`echo "scale=2;($dkze/$dkqc)/1 " | bc -l`
  17. whbj=$dkze
  18. for((i=1;i<=$dkqc;i++))
  19. do
  20. bylx=`echo "scale=2;($whbj*$dkyll)/1 " | bc -l`
  21. bybx=`echo "scale=2;($yhbj+$bylx)/1 " | bc -l`
  22. yhke=`echo "scale=2;($yhbj*$i)/1 " | bc -l`
  23. whbj=`echo "$dkze-$yhke " | bc -l`
  24. if [ $i -eq $dkqc ]
  25. then
  26. yhbj=`echo "scale=2;($yhbj+$whbj)/1 " | bc -l`
  27. whbj="0.00"
  28. bybx=`echo "scale=2;($yhbj+$bylx)/1 " | bc -l`
  29. fi
  30. echo "$i $bybx $bylx $whbj"
  31. done
  32. }
  33. debxjsf()
  34. {
  35. bybx=`echo "scale=2;(($dkze*$dkyll*((1+$dkyll)^$dkqc))/(((1+$dkyll)^$dkqc)-1))/1 " | bc -l`
  36. whbj=$dkze
  37. for((i=1;i<=$dkqc;i++))
  38. do
  39. bylx=`echo "scale=2;($whbj*$dkyll)/1 " | bc -l`
  40. yhbj=`echo "scale=2;($bybx-$bylx)/1 " | bc -l`
  41. whbj=`echo "scale=2;($whbj-$yhbj)/1 " | bc -l`
  42. if [ $i -eq $dkqc ]
  43. then
  44. bybx=`echo "scale=2;($yhbj+$whbj)/1 " | bc -l`
  45. whbj="0.00"
  46. fi
  47. echo "$i $bybx $bylx $whbj"
  48. done
  49. }
  50. case $dkfs in
  51. 1) debjjsf
  52. ;;
  53. 2) debxjsf
  54. ;;
  55. *) exit 1
  56. ;;
  57. esac

【脚本91】监控磁盘io

阿里云的机器,今天收到客服来的电话,说服务器的磁盘io很重。于是登录到服务器查看,并没有发现问题,所以怀疑是间歇性地。

正要考虑写个脚本的时候,幸运的抓到了一个线索,造成磁盘io很高的幕后黑手是mysql。此时去show processlist,但未发现队列。原来只是一瞬间。

只好继续来写脚本,思路是,每5s检测一次磁盘io,当发现问题去查询mysql的processlist。

提示:你可以用iostat -x 1 5 来判定磁盘的io,主要看%util

参考代码:

  1. #!/bin/bash
  2. while :
  3. do
  4. n=`iostat -x 1 5 |tail -n3|head -n1 |awk '{print $NF}'|cut -d. -f1`
  5. if [ $n -gt 70 ]
  6. then
  7. echo "`date` util% is $n%" >>/tmp/mysql_processlist.log
  8. mysql -uroot -pxxxxxx -e "show full processlist" >> /tmp/mysql_processlist.log
  9. fi
  10. sleep 5
  11. done

【脚本92】截取tomcat日志

写一个截取tomcat catalina.out日志的脚本。

tomcat实例t1-t4:

  1. [root@server ~]# tree -L 1 /opt/TOM/
  2. /opt/TOM/
  3. ├── crontabs
  4. ├── t1
  5. ├── t2
  6. ├── t3
  7. └── t4
  8. 5 directories, 0 files

catalina.out日志路径:

  1. [root@server ~]# find /opt/TOM/ -name catalina.out
  2. /opt/TOM/t1/logs/catalina.out
  3. /opt/TOM/t3/logs/catalina.out
  4. /opt/TOM/t4/logs/catalina.out
  5. /opt/TOM/t2/logs/catalina.out

要求:

  1. 这个脚本可以取tomcat实例t1-t4的日志
  2. 这个脚本可以自定义取日志的起始点,比如取今天早上10点之后到现在的数据
  3. 这个脚本可以自定义取日志的起始点和终点,比如取今天早上9点到晚上8点的数据

catalina.out 日志片段:

  1. Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start
  2. INFO: Starting ProtocolHandler [“http-bio-8080”]
  3. Mar 29, 2016 1:52:24 PM org.apache.coyote.AbstractProtocol start
  4. INFO: Starting ProtocolHandler [“ajp-bio-8009”]
  5. Mar 29, 2016 1:52:24 PM org.apache.catalina.startup.Catalina start
  6. INFO: Server startup in 2102 ms

参考代码:

  1. #!/bin/bash
  2. export LANG=en_US.UTF-8
  3. export PATH=$PATH
  4. IPADD=`/sbin/ifconfig | grep "inet addr" | head -1 | awk '{print $2}'| awk -F '.' '{print $NF}'`
  5. LOGFILE="/opt/TOM/$1/logs/catalina.out"
  6. YEAR=`date +%Y`
  7. DATE=`date +%m%d_%H%M`
  8. TOMCAT=$1
  9. BEGIN_TIME=$YEAR$2
  10. END_TIME=$YEAR$3
  11. ##judge is a.m.or p.m.
  12. TIME_HOUR1=`echo ${BEGIN_TIME:9:2}`
  13. cut_log() {
  14. N_DATE1=`echo $1 | sed 's/_/ /g'`
  15. D_DATE1=`echo $2 | sed 's/_/ /g'`
  16. E_DATE1=`echo $3 | sed 's/_/ /g'`
  17. [ $4 ] && N_DATE2=`echo $4 | sed 's/_/ /g'`
  18. [ $5 ] && D_DATE2=`echo $5 | sed 's/_/ /g'`
  19. [ $6 ] && E_DATE2=`echo $6 | sed 's/_/ /g'`
  20. BEGIN=`grep -nE "${N_DATE1}|${D_DATE1}|${E_DATE1}" ${LOGFILE} | head -1 | cut -d : -f1`
  21. [ "$N_DATE2" ] && END=`grep -nE "${N_DATE2}|${D_DATE2}|${E_DATE2}" ${LOGFILE} | tail -1 | cut -d : -f1`
  22. [ ! -z "${TIME_HOUR1}" ] && if [ ${TIME_HOUR1} -gt 12 ] ; then
  23. BEGIN1=`grep -nE "${N_DATE1}|${D_DATE1}|${E_DATE1}" ${LOGFILE} |grep " PM " |grep "${E_DATE1}" | head -1 | cut -d : -f1`
  24. if [ ! -z "${BEGIN1}" ] ; then
  25. [ "${BEGIN1}" -gt "${BEGIN}" ] ; BEGIN=${BEGIN1}
  26. fi
  27. fi
  28. if [ "$BEGIN" ] && [ -z "$END" ] ; then
  29. if [ "$N_DATE2" ]; then
  30. echo "${END_TIME}时间点没有访问日志,请重新设置时间点."
  31. else
  32. sed -n "${BEGIN},[ DISCUZ_CODE_0 ]quot;p ${LOGFILE} > /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log
  33. fi
  34. elif [ "$END" ];then
  35. [ "$BEGIN" ] || BEGIN=1
  36. sed -n "${BEGIN},${END}"p ${LOGFILE} > /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log
  37. else
  38. [ "$END_TIME" != "$YEAR" ] && echo "该时段 ${BEGIN_TIME}${END_TIME} 没有日志."
  39. [ "$END_TIME" = "$YEAR" ] && echo "该时段 ${BEGIN_TIME}~now 没有日志."
  40. fi
  41. if [ -s /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log ]; then
  42. cd /home/gcweb && tar -zcf ${IPADD}_${TOMCAT}_${DATE}.tar.gz ${IPADD}_${TOMCAT}_${DATE}.log
  43. rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.log
  44. sz /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz
  45. echo "Success to get logs."
  46. rm -f /home/gcweb/${IPADD}_${TOMCAT}_${DATE}.tar.gz
  47. fi
  48. }
  49. get_time() {
  50. case "$1" in
  51. 4)
  52. N_DATE=`date -d "$2" +"%Y-%m-%d" 2>/dev/null`
  53. D_DATE=`date -d "$2" +"%Y/%m/%d" 2>/dev/null`
  54. E_DATE=`date -d "$2" +"%h %e,_%Y" 2>/dev/null|sed 's/ /_/g'`
  55. echo $N_DATE $D_DATE $E_DATE
  56. ;;
  57. 7)
  58. TIME=`echo $2 | awk -F'_' '{print $1,$2}'`
  59. N_DATE=`date -d "$TIME" +"%Y-%m-%d_%H" 2>/dev/null`
  60. D_DATE=`date -d "$TIME" +"%Y/%m/%d_%H" 2>/dev/null`
  61. E_DATE=`date -d "$TIME" +"%h %e,_%Y %l" 2>/dev/null|sed 's/ /_/g'`
  62. echo "$N_DATE" "$D_DATE" "$E_DATE"
  63. ;;
  64. 9)
  65. TIME=`echo $2 | awk -F'_' '{print $1,$2}'`
  66. N_DATE=`date -d "$TIME" +"%Y-%m-%d_%H:%M" 2>/dev/null`
  67. D_DATE=`date -d "$TIME" +"%Y/%m/%d_%H:%M" 2>/dev/null`
  68. E_DATE=`date -d "$TIME" +"%h %e,_%Y %l:%M" 2>/dev/null|sed 's/ /_/g'`
  69. echo "$N_DATE" "$D_DATE" "$E_DATE"
  70. ;;
  71. *)
  72. echo 1
  73. ;;
  74. esac
  75. }
  76. check_arguments () {
  77. if [ "$1" == 1 ] || [ -z "$1" ] ;then
  78. echo "你输入时间参数的格式无法识别, usage: 0108、0108_10、0108_1020"
  79. exit 3
  80. fi
  81. }
  82. check_tomcat () {
  83. if [ ! -s "${LOGFILE}" ] ;then
  84. echo "tomcat_name: ${TOMCAT} is not exist"
  85. echo "you can choose:"
  86. /bin/ls /home/gcweb/usr/local/
  87. fi
  88. if [ $1 -lt 2 ] || [ ! -s "${LOGFILE}" ];then
  89. echo "usage: $0 tomcat_name {begin_time|begin_time end_time}"
  90. exit 2
  91. fi
  92. }
  93. case "$#" in
  94. 0)
  95. echo "usage: $0 tomcat_name {begin_time|begin_time end_time}"
  96. exit 1
  97. ;;
  98. 1)
  99. check_tomcat $#
  100. ;;
  101. 2)
  102. check_tomcat $#
  103. len=`echo $2 | awk '{print length($0)}'`
  104. A_DATE=$(get_time $len $BEGIN_TIME)
  105. eval $( echo $A_DATE |awk '{print "N_DATE="$1,"D_DATE="$2,"E_DATE="$3}')
  106. check_arguments "${N_DATE}"
  107. cut_log "${N_DATE}" "${D_DATE}" "${E_DATE}"
  108. ;;
  109. 3)
  110. check_tomcat $#
  111. len1=`echo $2 | awk '{print length($0)}'`
  112. len2=`echo $3 | awk '{print length($0)}'`
  113. A_DATE=$(get_time ${len1} $BEGIN_TIME)
  114. eval $( echo $A_DATE |awk '{print "N_DATE1="$1,"D_DATE1="$2,"E_DATE1="$3}')
  115. check_arguments "${N_DATE1}"
  116. A_DATE=$(get_time ${len2} $END_TIME)
  117. eval $( echo $A_DATE |awk '{print "N_DATE="$1,"D_DATE="$2,"E_DATE="$3}')
  118. check_arguments "${N_DATE}"
  119. cut_log ${N_DATE1} ${D_DATE1} ${E_DATE1} "${N_DATE}" "${D_DATE}" "${E_DATE}"
  120. ;;
  121. *)
  122. echo "usage: $0 tomcat_name {begin_time|begin_time end_time};你使用的参数太多哦."
  123. ;;
  124. esac

【脚本93】数组

写一个脚本让用户输入多个城市的名字(可以是中文),要求不少于5个,然后把这些城市存到一个数组里,最后用for循环把它们打印出来。

参考代码:

  1. #!/bin/bash
  2. read -p "请输入至少5个城市的名字,用空格分隔:" city
  3. n=`echo $city|awk '{print NF}'`
  4. if [ $n -lt 5 ]
  5. then
  6. echo "输入的城市个数至少为5"
  7. exit
  8. fi
  9. name=($city)
  10. for i in ${name[@]}
  11. do
  12. echo $i
  13. done

【脚本94】批量同步代码

需求背景是:

一个业务,有3台服务器(A,B,C)做负载均衡,由于规模太小目前并未使用专业的自动化运维工具。有新的需求时,开发同事改完代码会把变更上传到其中一台服务器A上。但是其他2台服务器也需要做相同变更。

写一个shell脚本,把A服务器上的变更代码同步到B和C上。

其中,你需要考虑到不需要同步的目录(假如有tmp、upload、logs、caches)

参考代码:

  1. #!/bin/bash
  2. echo "该脚本将会把A机器上的/data/wwwroot/www.aaa.com目录同步到B,C机器上";
  3. read -p "是否要继续?(y|n) "
  4. rs() {
  5. rsync -azP \
  6. --exclude logs \
  7. --exclude upload \
  8. --exclude caches \
  9. --exclude tmp \
  10. www.aaa.com/ $1:/data/wwwroot/www.aaa.com/
  11. }
  12. if [ $REPLY == 'y' -o $REPLY == 'Y' ]
  13. then
  14. echo "即将同步……"
  15. sleep 2
  16. cd /data/wwwroot/
  17. rs B机器ip
  18. rs C机器ip
  19. echo "同步完成。"
  20. elif [ $REPLY == 'n' -o $REPLY == 'N' ]
  21. then
  22. exit 1
  23. else
  24. echo "请输入字母y或者n"
  25. fi

【脚本95】统计并发量

需求背景:

  • 需要统计网站的并发量,并绘图。

思路:

  1. 借助zabbix成图
  2. 通过统计访问日志每秒的日志条数来判定并发量
  3. zabbix获取数据间隔30s

说明: 只需要写出shell脚本即可,不用关心zabbix配置。

假设日志路径为:

/data/logs/www.aaa.com_access.log 

日志格式如下:

112.107.15.12 - [07/Nov/2017:09:59:01 +0800] www.aaa.com "/api/live.php" 200"-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"

参考代码:

  1. #!/bin/bash
  2. log=/data/logs/www.aaa.com_access.log
  3. t=`date -d "-1 second" +%Y:%H:%M:%S`
  4. #可以大概分析一下每分钟日志的量级,比如说不超过3000
  5. n=tail -3000 $log |grep -c "$t"
  6. echo $n

【脚本96】关闭服务

在centos6系统里,我们可以使用ntsysv关闭不需要开机启动的服务,当然也可以使用chkconfig工具来实现。

写一个shell脚本,用chkconfig工具把不常用的服务关闭。脚本需要写成交互式的,需要我们给它提供关闭的服务名字。

参考代码:

  1. #!/bin/bash
  2. LANG=en
  3. c="1"
  4. while [ ! $c == "q" ]
  5. do
  6. echo -e "\033[35mPlease chose a service to close from this list: \033[0m"
  7. chkconfig --list |awk '/3:on/ {print $1}'
  8. read -p "Which service to close: " s
  9. chkconfig $s off
  10. service $s stop
  11. read -p "If you want's to quit this program, tab "q", or tab "Ctrl c": " c
  12. done

【脚本97】重启tomcat服务

在生产环境中,经常遇到tomcat无法彻底关闭,也就是说用tomcat自带shutdown.sh脚本无法将java进程完全关掉。所以,需要借助shell脚本,将进程杀死,然后再启动。

写一个shell脚本,实现上述功能。彻底杀死一个进程的命令是 kill -9 pid.

参考代码:

  1. #!/bin/bash
  2. ###功能: 重启 tomcat 进程
  3. ###要求:对于tomcat中的某些应用,使用shutdown.sh是无法完全停掉所有服务的 实际操作中都需要kill掉tomcat再重启
  4. ##
  5. ### root can not run this script.
  6. ##
  7. if [ $USER = root ]
  8. then
  9. echo "root cann't run this script!please run with other user!"
  10. exit 1
  11. fi
  12. ##
  13. ### check the Parameter
  14. ##
  15. if [[ $# -ne 1 ]]
  16. then
  17. echo "Usage:$0 tomcatname"
  18. exit 1
  19. fi
  20. ##
  21. ### only one process can run one time
  22. ##
  23. TMP_FILE_U=/tmp/.tmp.ps.keyword.$USER.956327.txt
  24. #echo $TMP_FILE_U
  25. KEYWORD1="$0"
  26. KEYWORD2="$1"
  27. # 使用赋值会多fork出一个进程,所以要先重定向到一个文本,再统计.
  28. ps ux |grep "$KEYWORD1"|grep "\<$KEYWORD2\>"|grep -v "grep" > $TMP_FILE_U
  29. Pro_count=`cat $TMP_FILE_U |wc -l`
  30. if [ $Pro_count -gt 1 ]
  31. then
  32. echo "An other process already running ,exit now!"
  33. exit 1
  34. fi
  35. ###################################################
  36. # #
  37. # begin of the script #
  38. # #
  39. ###################################################
  40. ##
  41. ### set the Parameter
  42. ##
  43. TOM=`echo $1|sed 's#/##g'`
  44. TOMCAT_DIRECTORY=~/usr/local/$TOM
  45. STARTUP_SCRIPT=$TOMCAT_DIRECTORY/bin/startup.sh
  46. TOMCAT_LOG=$TOMCAT_DIRECTORY/logs/catalina.out
  47. CONF_FILE=$TOMCAT_DIRECTORY/conf/server.xml
  48. TEMPFILE=/tmp/.tmpfile.x.89342.c4r3.tmp
  49. ##
  50. ### check if the tomcat directory exist
  51. ##
  52. if [ ! -d "$TOMCAT_DIRECTORY" ]
  53. then
  54. echo "the tomcat \"$TOM\" not exist.check again!"
  55. exit 1
  56. fi
  57. ##
  58. ### log roteta and delete log one week ago
  59. ##
  60. rotate_log(){
  61. TIME_FORMART=$(date +%Y%m%d%H%M%S)
  62. LOG_DIR=$(dirname $TOMCAT_LOG)
  63. mv $TOMCAT_LOG ${TOMCAT_LOG}_${TIME_FORMART}
  64. find $LOG_DIR -type f -ctime +7 -exec rm -rf {} \;
  65. }
  66. ##
  67. ### function start the tomcat
  68. ##
  69. start_tomcat()
  70. {
  71. #echo start-tomcat-func
  72. if [ -x "$STARTUP_SCRIPT" ]
  73. then
  74. rotate_log
  75. $STARTUP_SCRIPT
  76. sleep 1
  77. tail -f $TOMCAT_LOG
  78. else
  79. if [ -e $STARTUP_SCRIPT ]
  80. then
  81. chmod +x $STARTUP_SCRIPT
  82. # echo "permition added!"
  83. if [ -x "$STARTUP_SCRIPT" ]
  84. then
  85. rotate_log
  86. $STARTUP_SCRIPT
  87. sleep 1
  88. tail -f $TOMCAT_LOG
  89. else
  90. echo "The script not have excute permision,Couldn't add permision to Script!"
  91. exit 1
  92. fi
  93. else
  94. echo "error,the script \"startup.sh\" not exist!"
  95. exit 1
  96. fi
  97. fi
  98. }
  99. ##
  100. ### function stop the tomcat
  101. ##
  102. stop_tomcat()
  103. {
  104. rm -rf $TEMPFILE
  105. ps ux |grep /$TOM/ |grep -v "grep /$TOM/"|grep java > $TEMPFILE
  106. Pro_Count=`cat $TEMPFILE|wc -l`
  107. PIDS=`cat $TEMPFILE|awk '{print $2}'`
  108. rm -rf $TEMPFILE
  109. #echo $Pro_Count
  110. if [ $Pro_Count -eq 0 ]
  111. then
  112. echo "The tomcat not running now!"
  113. else
  114. if [ $Pro_Count -ne 1 ]
  115. then
  116. echo "The have $Pro_Count process running,killed!"
  117. kill -9 `echo $PIDS`
  118. WC=`ps aux | grep "/$TOM/" | grep -v "grep /$TOM/" | grep java |wc -l`
  119. [ $WC -ne 0 ] && (echo "kill process failed!";exit 1)
  120. else
  121. echo "Process killed!"
  122. kill -9 `echo $PIDS`
  123. WC=`ps aux | grep "/$TOM/" | grep -v "grep /$TOM/" | grep java |wc -l`
  124. [ $WC -ne 0 ] && (echo "kill process failed!";exit 1)
  125. fi
  126. fi
  127. }
  128. ###########################
  129. #### ####
  130. #### The main script ####
  131. #### ####
  132. ###########################
  133. echo -e "are you sure restart $TOM?(y or n)"
  134. read ANS
  135. if [ "$ANS"a != ya ]
  136. then
  137. echo -e "bye! \n"
  138. exit 1
  139. fi
  140. stop_tomcat
  141. echo "start tomcat ..."
  142. sleep 2
  143. start_tomcat
  144. # end

【脚本98】取消后缀

至少用两种方法,批量把当前目录下面所有文件名后缀为.bak的后缀去掉,比如1.txt.bak去掉后为1.txt

假设取消的后缀为.bak

方法一:

  1. #!/bin/bash
  2. for i in `ls *.bak`
  3. do
  4. mv $i `echo $i|sed 's/\.bak//g'`
  5. done

方法二:

  1. #!/bin/bash
  2. for i in `ls *.bak`
  3. do
  4. newname=`echo $i|awk -F '.bak' '{print $1}'`
  5. mv $i $newname
  6. done

【脚本99】域名到期提醒

写一个shell脚本,查询指定域名的过期时间,并在到期前一周,每天发一封提醒邮件。

思路: 大家可以在linux下使用命令“whois 域名”,如”whois xxx.com”,来获取该域名的一些信息。

提示: whois命令,需要安装jwhois包

参考代码:

  1. #!/bin/bash
  2. t1=`date +%s`
  3. is_install_whois()
  4. {
  5. which whois >/dev/null 2>/dev/null
  6. if [ $? -ne 0 ]
  7. then
  8. yum install -y jwhois
  9. fi
  10. }
  11. notify()
  12. {
  13. e_d=`whois $1|grep 'Expiry Date'|awk '{print $4}'|cut -d 'T' -f 1`
  14. e_t=`date -d "$e_d" +%s`
  15. n=`echo "86400*7"|bc`
  16. e_t1=$[$e_t-$n]
  17. if [ $t1 -ge $e_t1 ] && [ $t1 -lt $e_t ]
  18. then
  19. /usr/local/sbin/mail.py aming_test@163.com "Domain $1 will be expire." "Domain $1 expire date is $e_d."
  20. fi
  21. }
  22. is_install_whois
  23. notify xxx.com

【脚本100】自动增加公钥

写一个shell脚本,当我们执行时,提示要输入对方的ip和root密码,然后可以自动把本机的公钥增加到对方机器上,从而实现密钥认证。

参考代码:

  1. #!/bin/bash
  2. read -p "Input IP: " ip
  3. ping $ip -w 2 -c 2 >> /dev/null
  4. ## 查看ip是否可用
  5. while [ $? -ne 0 ]
  6. do
  7. read -p "your ip may not useable, Please Input your IP: " ip
  8. ping $ip -w 2 -c 2 >> /dev/null
  9. done
  10. read -p "Input root\'s password of this host: " password
  11. ## 检查命令子函数
  12. check_ok() {
  13. if [ $? != 0 ]
  14. then
  15. echo "Error!."
  16. exit 1
  17. fi
  18. }
  19. ## yum需要用到的包
  20. myyum() {
  21. if ! rpm -qa |grep -q "$1"
  22. then
  23. yum install -y $1
  24. check_ok
  25. else
  26. echo $1 already installed
  27. fi
  28. }
  29. for p in openssh-clients openssh expect
  30. do
  31. myyum $p
  32. done
  33. ## 在主机A上创建密钥对
  34. if [ ! -f ~/.ssh/id_rsa ] || [ ! -f ~/.ssh/id_rsa.pub ]
  35. then
  36. if [ -d ~/.ssh ]
  37. then
  38. mv ~/.ssh/ ~/.ssh_old
  39. fi
  40. echo -e "\n" | ssh-keygen -t rsa -P ''
  41. check_ok
  42. fi
  43. ## 传私钥给主机B
  44. if [ ! -d /usr/local/sbin/rsync_keys ]
  45. then
  46. mkdir /usr/local/sbin/rsync_keys
  47. fi
  48. cd /usr/local/sbin/rsync_keys
  49. if [ -f rsync.expect ]
  50. then
  51. d=`date +%F-%T`
  52. mv rsync.expect $d.expect
  53. fi
  54. #创建远程同步的expect文件
  55. cat > rsync.expect <<EOF
  56. #!/usr/bin/expect
  57. set host [lindex \$argv 0]
  58. #主机B的密码
  59. set passwd [lindex \$argv 1]
  60. spawn rsync -av /root/.ssh/id_rsa.pub root@\$host:/tmp/tmp.txt
  61. expect {
  62. "yes/no" { send "yes\r"; exp_continue}
  63. "password:" { send "\$passwd\r" }
  64. }
  65. expect eof
  66. spawn ssh root@\$host
  67. expect {
  68. "password:" { send "\$passwd\r" }
  69. }
  70. expect "]*"
  71. send "\[ -f /root/.ssh/authorized_keys \] && cat /tmp/tmp.txt >>/root/.ssh/authorized_keys \r"
  72. expect "]*"
  73. send "\[ -f /root/.ssh/authorized_keys \] || mkdir -p /root/.ssh/ \r"
  74. send "\[ -f /root/.ssh/authorized_keys \] || mv /tmp/tmp.txt /root/.ssh/authorized_keys\r"
  75. expect "]*"
  76. send "chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys\r"
  77. expect "]*"
  78. send "exit\r"
  79. EOF
  80. check_ok
  81. /usr/bin/expect /usr/local/sbin/rsync_keys/rsync.expect $ip $password
  82. echo "OK,this script is successful. ssh $ip to test it"

【脚本101】自动封/解封ip

需求背景:

discuz论坛,每天有很多注册机注册的用户,然后发垃圾广告帖子。虽然使用了一些插件但没有效果。分析访问日志,发现有几个ip访问量特别大,所以想到可以写个shell脚本,通过分析访问日志,把访问量大的ip直接封掉。

但是这个脚本很有可能误伤,所以还需要考虑到自动解封这些ip。

思路:

  1. 可以每分钟分析1次访问日志,设定一个阈值,把访问量大的ip用iptables封掉80端口
  2. 每20分钟检测一次已经被封ip的请求数据包数量,设定阈值,把没有请求的或者请求量很小的解封

参考代码:

  1. #! /bin/bash
  2. ## To block the ip of bad requesting.
  3. ## Writen by aming 2017-11-18.
  4. log="/data/logs/www.xxx.com.log"
  5. tmpdir="/tmp/badip"
  6. #白名单ip,不应该被封
  7. goodip="27.133.28.101"
  8. [ -d $tmpdir ] || mkdir -p $tmpdir
  9. t=`date -d "-1 min" +%Y:%H:%M`
  10. #截取一分钟以前的日志
  11. grep "$t:" $log > $tmpdir/last_min.log
  12. #把一分钟内日志条数大于120的标记为不正常的请求
  13. awk '{print $1}' $tmpdir/last_min.log |sort -n |uniq -c |sort -n |tail |awk '$1>120 {print $2}'|grep -v "$good_ip"> $tmpdir/bad.ip
  14. d3=`date +%M`
  15. #每隔20分钟解封一次ip
  16. if [ $d3 -eq "20" ] || [ $d3 -eq "40" ] || [ $d3 -eq "00" ]
  17. then
  18. /sbin/iptables -nvL INPUT|grep 'DROP' |awk '$1<10 {print $8}'>$tmpdir/good.ip
  19. if [ -s $tmpdir/good.ip ]
  20. then
  21. for ip in `cat $tmpdir/good.ip`
  22. do
  23. /sbin/iptables -D INPUT -p tcp --dport 80 -s $ip -j DROP
  24. d4=`date +%Y%m%d-%H:%M`
  25. echo "$d4 $ip unblock" >>$tmpdir/unblock.ip
  26. done
  27. fi
  28. #解封后,再把iptables的计数器清零
  29. /sbin/iptables -Z INPUT
  30. fi
  31. if [ -s $tmpdir/bad.ip ]
  32. then
  33. for ip in `cat $tmpdir/bad.ip`
  34. do
  35. /sbin/iptables -A INPUT -p tcp --dport 80 -s $ip -j DROP
  36. d4=`date +%Y%m%d-%H:%M`
  37. echo "$d4 $ip block" >>$tmpdir/block.ip
  38. done
  39. fi

【脚本102】单机部署SpringBoot项目

有一台测试服务器,经常需要部署SpringBoot项目,手动部署太麻烦,于是写了个部署脚本

脚本代码:

  1. #!/bin/bash
  2. # git仓库路径
  3. GIT_REPOSITORY_HOME=/app/developer/git-repository
  4. # jar包发布路径
  5. PROD_HOME=/prod/java-back
  6. # 应用列表
  7. APPS=(app1 app2 app3)
  8. if [ ! -n "$1" ]
  9. then
  10. echo -e "请输入要发布的项目!"
  11. exit
  12. fi
  13. # cd dir
  14. for((i=0;i<${#APPS[@]};i++))
  15. do
  16. echo $1 ${APPS[i]}
  17. if [ $1 = ${APPS[i]} ]
  18. then
  19. echo -e ===========Enter $1=============
  20. cd ${GIT_REPOSITORY_HOME}/$1
  21. break
  22. fi
  23. done
  24. if [ `pwd` != ${GIT_REPOSITORY_HOME}/$1 ]
  25. then
  26. echo -e "输入的项目名没有找到!"
  27. exit
  28. fi
  29. echo "==========git切换分之到master==============="
  30. git checkout master
  31. echo "==================git fetch======================"
  32. git fetch
  33. echo "==================git pull======================"
  34. git pull
  35. echo "===========选择线上环境编译并跳过单元测试===================="
  36. mvn clean package -Dmaven.test.skip=true -Pprod
  37. jar_path=${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar
  38. echo ${jar_path}
  39. if [ -f ${jar_path} ]
  40. then
  41. # backup dest
  42. echo -e "===========jar backup============="
  43. mv ${PROD_HOME}/$1/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1/$1-0.0.1-SNAPSHOT.jar.back
  44. # copy
  45. echo "======拷贝编译出来的jar包拷贝到$PROD_HOME======="
  46. if [ -d ${PROD_HOME}/$1 ]
  47. then
  48. /bin/cp ${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1
  49. else
  50. mkdir ${PROD_HOME}/$1
  51. /bin/cp ${GIT_REPOSITORY_HOME}/$1/target/*-0.0.1-SNAPSHOT.jar ${PROD_HOME}/$1
  52. fi
  53. echo "============停止项目============="
  54. jar_name=`jps |awk -F" " '{ print $2 }'| egrep ^$1.*jar$`
  55. pid=`jps |grep ${jar_name} | awk -F" " '{ print $1 }'`
  56. echo ${pid}
  57. kill -15 ${pid}
  58. echo "================sleep 10s========================="
  59. for i in 1 2 3 4 5 6 7 8 9 10
  60. do
  61. echo ${i}"s"
  62. sleep 1s
  63. done
  64. echo "============启动项目============="
  65. nohup java -jar ${PROD_HOME}/$1/*-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &
  66. echo -e "===========Deploy Success============="
  67. else
  68. echo -e "===========Deploy Error============="
  69. fi

转载于:https://blog.51cto.com/zero01/2046242

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号