超实用!18 个开箱即用的 Shell 脚本,拿好了

开发 前端
本文介绍十分实用的Shell脚本,建议收藏。

[[394986]]

 1、检测两台服务器指定目录下的文件一致性

  1. #!/bin/bash 
  2.  
  3. ###################################### 
  4.  
  5. 检测两台服务器指定目录下的文件一致性 
  6.  
  7. ##################################### 
  8.  
  9. #通过对比两台服务器上文件的md5值,达到检测一致性的目的 
  10.  
  11. dir=/data/web 
  12.  
  13. b_ip=192.168.88.10 
  14.  
  15. #将指定目录下的文件全部遍历出来并作为md5sum命令的参数,进而得到所有文件的md5值,并写入到指定文件中 
  16.  
  17. find $dir -type f|xargs md5sum > /tmp/md5_a.txt 
  18.  
  19. ssh $b_ip "find $dir -type f|xargs md5sum > /tmp/md5_b.txt" 
  20.  
  21. scp $b_ip:/tmp/md5_b.txt /tmp 
  22.  
  23. #将文件名作为遍历对象进行一一比对 
  24.  
  25. for f in `awk '{print 2} /tmp/md5_a.txt'`do 
  26.  
  27. #以a机器为标准,当b机器不存在遍历对象中的文件时直接输出不存在的结果 
  28.  
  29. if grep -qw "$f" /tmp/md5_b.txt 
  30.  
  31. then 
  32.  
  33. md5_a=`grep -w "$f" /tmp/md5_a.txt|awk '{print 1}'
  34.  
  35. md5_b=`grep -w "$f" /tmp/md5_b.txt|awk '{print 1}'
  36.  
  37. #当文件存在时,如果md5值不一致则输出文件改变的结果 
  38.  
  39. if [ $md5_a != $md5_b ]then 
  40.  
  41. echo "$f changed." 
  42.  
  43. fi 
  44.  
  45. else 
  46.  
  47. echo "$f deleted." 
  48.  
  49. fi 
  50.  
  51. done 

2、定时清空文件内容,定时记录文件大小

  1. #!/bin/bash 
  2.  
  3. ################################################################# 
  4.  
  5. 每小时执行一次脚本(任务计划),当时间为0点或12点时,将目标目录下的所有文件内#容清空,但不删除文件,其他时间则只统计各个文件的大小,一个文件一行,输出到以时#间和日期命名的文件中,需要考虑目标目录下二级、三级等子目录的文件 
  6.  
  7. ################################################################ 
  8.  
  9. logfile=/tmp/`date +%H-%F`.log 
  10.  
  11. n=`date +%H` 
  12.  
  13. if [ $n -eq 00 ] || [ $n -eq 12 ] 
  14.  
  15. then 
  16.  
  17. #通过for循环,以find命令作为遍历条件,将目标目录下的所有文件进行遍历并做相应操作 
  18.  
  19. for i in `find /data/log/ -type f` 
  20.  
  21. do 
  22.  
  23. true > $i 
  24.  
  25. done 
  26.  
  27. else 
  28.  
  29. for i in `find /data/log/ -type f` 
  30.  
  31. do 
  32.  
  33. du -sh $i >> $logfile 
  34.  
  35. done 
  36.  
  37. fi 

3、检测网卡流量,并按规定格式记录在日志中

  1. #!/bin/bash 
  2.  
  3. ####################################################### 
  4.  
  5. #检测网卡流量,并按规定格式记录在日志中#规定一分钟记录一次 
  6.  
  7. #日志格式如下所示: 
  8.  
  9. #2019-08-12 20:40 
  10.  
  11. #ens33 input: 1234bps 
  12.  
  13. #ens33 output: 1235bps 
  14.  
  15. ######################################################3 
  16.  
  17. while : 
  18.  
  19. do 
  20.  
  21. #设置语言为英文,保障输出结果是英文,否则会出现bug 
  22.  
  23. LANG=en 
  24.  
  25. logfile=/tmp/`date +%d`.log 
  26.  
  27. #将下面执行的命令结果输出重定向到logfile日志中 
  28.  
  29. exec >> $logfile 
  30.  
  31. date +"%F %H:%M" 
  32.  
  33. #sar命令统计的流量单位为kb/s,日志格式为bps,因此要*1000*8 
  34.  
  35. sar -n DEV 1 59|grep Average|grep ens33|awk '{print $2,"\t","input:","\t",$5*1000*8,"bps","\n",$2,"\t","output:","\t",$6*1000*8,"bps"}' 
  36.  
  37. echo "####################" 
  38.  
  39. #因为执行sar命令需要59秒,因此不需要sleep 
  40.  
  41. done 

4、计算文档每行出现的数字个数,并计算整个文档的数字总数

  1. #!/bin/bash 
  2.  
  3. ######################################################### 
  4.  
  5. #计算文档每行出现的数字个数,并计算整个文档的数字总数 
  6.  
  7. ######################################################## 
  8.  
  9. #使用awk只输出文档行数(截取第一段) 
  10.  
  11. n=`wc -l a.txt|awk '{print $1}'
  12.  
  13. sum=0 
  14.  
  15. #文档中每一行可能存在空格,因此不能直接用文档内容进行遍历 
  16.  
  17. for i in `seq 1 $n`do 
  18.  
  19. #输出的行用变量表示时,需要用双引号 
  20.  
  21. line=`sed -n "$i"p a.txt`#wc -L选项,统计最长行的长度 
  22.  
  23. n_n=`echo $line|sed s'/[^0-9]//'g|wc -L` 
  24.  
  25. echo $n_nsum=$[$sum+$n_n] 
  26.  
  27. done 
  28.  
  29. echo "sum:$sum" 
  30.  
  31. 杀死所有脚本 
  32.  
  33. #!/bin/bash 
  34.  
  35. ################################################################ 
  36.  
  37. #有一些脚本加入到了cron之中,存在脚本尚未运行完毕又有新任务需要执行的情况, 
  38.  
  39. #导致系统负载升高,因此可通过编写脚本,筛选出影响负载的进程一次性全部杀死。 
  40.  
  41. ################################################################ 
  42.  
  43. ps aux|grep 指定进程名|grep -v grep|awk '{print $2}'|xargs kill -9 

5、从 FTP 服务器下载文件

  1. #!/bin/bash 
  2.  
  3. if [ $# -ne 1 ]; then 
  4.  
  5. echo "Usage: $0 filename" 
  6.  
  7. fi 
  8.  
  9. dir=$(dirname $1
  10.  
  11. file=$(basename $1
  12.  
  13. ftp -n -v << EOF # -n 自动登录 
  14.  
  15. open 192.168.1.10 # ftp服务器 
  16.  
  17. user admin password 
  18.  
  19. binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误 
  20.  
  21. cd $dir 
  22.  
  23. get "$file" 
  24.  
  25. EOF 

6、连续输入5个100以内的数字,统计和、最小和最大

  1. #!/bin/bash 
  2.  
  3. COUNT=1 
  4.  
  5. SUM=0 
  6.  
  7. MIN=0 
  8.  
  9. MAX=100 
  10.  
  11. while [ $COUNT -le 5 ]; do 
  12.  
  13. read -p "请输入1-10个整数:" INT 
  14.  
  15. if [[ ! $INT =~ ^[0-9]+$ ]]; then 
  16.  
  17. echo "输入必须是整数!" 
  18.  
  19. exit 1 
  20.  
  21. elif [[ $INT -gt 100 ]]; then 
  22.  
  23. echo "输入必须是100以内!" 
  24.  
  25. exit 1 
  26.  
  27. fi 
  28.  
  29. SUM=$(($SUM+$INT)) 
  30.  
  31. [ $MIN -lt $INT ] && MIN=$INT 
  32.  
  33. [ $MAX -gt $INT ] && MAX=$INT 
  34.  
  35. let COUNT++ 
  36.  
  37. done 
  38.  
  39. echo "SUM: $SUM" 
  40.  
  41. echo "MIN: $MIN" 
  42.  
  43. echo "MAX: $MAX 

用户猜数字

  1. #!/bin/bash # 脚本生成一个 100 以内的随机数,提示用户猜数字,根据用户的输入,提示用户猜对了,# 猜小了或猜大了,直至用户猜对脚本结束。# RANDOM 为系统自带的系统变量,值为 032767的随机数# 使用取余算法将随机数变为 1100 的随机数num=$[RANDOM%100+1]echo "$num" # 使用 read 提示用户猜数字# 使用 if 判断用户猜数字的大小关系:‐eq(等于),‐ne(不等于),‐gt(大于),‐ge(大于等于),# ‐lt(小于),‐le(小于等于)while :do read -p "计算机生成了一个 1‐100 的随机数,你猜: " cai if [ $cai -eq $num ] then echo "恭喜,猜对了" exit elif [ $cai -gt $num ] then echo "Oops,猜大了" else echo "Oops,猜小了" fidone 

7、监测 Nginx 访问日志 502 情况,并做相应动作

假设服务器环境为 lnmp,近期访问经常出现 502 现象,且 502 错误在重启 php-fpm 服务后消失,因此需要编写监控脚本,一旦出现 502,则自动重启 php-fpm 服务。

  1. #场景: 
  2.  
  3. #1.访问日志文件的路径:/data/log/access.log 
  4.  
  5. #2.脚本死循环,每10秒检测一次,10秒的日志条数为300条,出现502的比例不低于10%(30条)则需要重启php-fpm服务 
  6.  
  7. #3.重启命令为:/etc/init.d/php-fpm restart 
  8.  
  9. #!/bin/bash 
  10.  
  11. ########################################################### 
  12.  
  13. #监测Nginx访问日志502情况,并做相应动作 
  14.  
  15. ########################################################### 
  16.  
  17. log=/data/log/access.log 
  18.  
  19. N=30 #设定阈值 
  20.  
  21. while :do 
  22.  
  23. #查看访问日志的最新300条,并统计502的次数 
  24.  
  25. err=`tail -n 300 $log |grep -c '502" '
  26.  
  27. if [ $err -ge $N ] 
  28.  
  29. then 
  30.  
  31. /etc/init.d/php-fpm restart 2> /dev/null 
  32.  
  33. #设定60s延迟防止脚本bug导致无限重启php-fpm服务 
  34.  
  35. sleep 60 
  36.  
  37. fi 
  38.  
  39. sleep 10 
  40.  
  41. done 

8、将结果分别赋值给变量

  1. 应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。 
  2.  
  3. 方法1: 
  4.  
  5. for i in $(echo "4 5 6"); do 
  6.  
  7. eval a$i=$idone 
  8.  
  9. echo $a4 $a5 $a6 
  10.  
  11. 方法2:将位置参数192.168.1.1{1,2}拆分为到每个变量 
  12.  
  13. num=0 
  14.  
  15. for i in $(eval echo $*);do #eval将{1,2}分解为1 2 
  16.  
  17. let num+=1 
  18.  
  19. eval node${num}="$i" 
  20.  
  21. done 
  22.  
  23. echo $node1 $node2 $node3 
  24.  
  25. # bash a.sh 192.168.1.1{1,2
  26.  
  27. 192.168.1.11 192.168.1.12 
  28.  
  29. 方法3:arr=(4 5 6
  30.  
  31. INDEX1=$(echo ${arr[0]}) 
  32.  
  33. INDEX2=$(echo ${arr[1]}) 
  34.  
  35. INDEX3=$(echo ${arr[2]}) 

9、批量修改文件名

  1. 示例: 
  2.  
  3. # touch article_{1..3}.html 
  4.  
  5. # lsarticle_1.html article_2.html article_3.html 
  6.  
  7. 目的:把article改为bbs 
  8.  
  9. 方法1: 
  10.  
  11. for file in $(ls *html); do 
  12.  
  13. mv $file bbs_${file#*_} 
  14.  
  15. # mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/'
  16.  
  17. # mv $file $(echo $file |echo bbs_$(cut -d_ -f2) 
  18.  
  19. done 
  20.  
  21. 方法2: 
  22.  
  23. for file in $(find . -maxdepth 1 -name "*html"); do 
  24.  
  25. mv $file bbs_${file#*_}done 
  26.  
  27. 方法3: 
  28.  
  29. # rename article bbs *.html 

把一个文档前五行中包含字母的行删掉,同时删除6到10行包含的所有字母

1)准备测试文件,文件名为2.txt

  1. 11234567不包含字母 
  2.  
  3. 2行56789BBBBBB 
  4.  
  5. 3行67890CCCCCCCC 
  6.  
  7. 4行78asdfDDDDDDDDD 
  8.  
  9. 5行123456EEEEEEEE 
  10.  
  11. 6行1234567ASDF 
  12.  
  13. 7行56789ASDF 
  14.  
  15. 8行67890ASDF 
  16.  
  17. 9行78asdfADSF 
  18.  
  19. 10行123456AAAA 
  20.  
  21. 11行67890ASDF 
  22.  
  23. 12行78asdfADSF 
  24.  
  25. 13行123456AAAA 

2)脚本如下:

  1. #!/bin/bash 
  2.  
  3. ############################################################### 
  4.  
  5. 把一个文档前五行中包含字母的行删掉,同时删除610行包含的所有字母 
  6.  
  7. ############################################################## 
  8.  
  9. sed -n '1,5'2.txt |sed '/[a-zA-Z]/'
  10.  
  11. sed -n '6,10'2.txt |sed s'/[a-zA-Z]//'
  12.  
  13. sed -n '11,$'2.txt 
  14.  
  15. #最终结果只是在屏幕上打印结果,如果想直接更改文件,可将输出结果写入临时文件中,再替换2.txt或者使用-i选项 

10、统计当前目录中以.html结尾的文件总大

  1. 方法1: 
  2.  
  3. # find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}' 
  4.  
  5. 方法2: 
  6.  
  7. for size in $(ls -l *.html |awk '{print $5}'); do 
  8.  
  9. sum=$(($sum+$size)) 
  10.  
  11. done 
  12.  
  13. echo $sum 

11、扫描主机端口状态

  1. #!/bin/bash 
  2.  
  3. HOST=$1 
  4.  
  5. PORT="22 25 80 8080" 
  6.  
  7. for PORT in $PORT; do 
  8.  
  9. if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then 
  10.  
  11. echo "$PORT open" 
  12.  
  13. else 
  14.  
  15. echo "$PORT close" 
  16.  
  17. fi 
  18.  
  19. done 
  20.  
  21. 用 shell 打印示例语句中字母数小于6的单词 
  22.  
  23. #示例语句: 
  24.  
  25. #Bash also interprets a number of multi-character options. 
  26.  
  27. #!/bin/bash 
  28.  
  29. ############################################################## 
  30.  
  31. #shell打印示例语句中字母数小于6的单词 
  32.  
  33. ############################################################## 
  34.  
  35. for s in Bash also interprets a number of multi-character options. 
  36.  
  37. do 
  38.  
  39. n=`echo $s|wc -c` 
  40.  
  41. if [ $n -lt 6 ] 
  42.  
  43. then 
  44.  
  45. echo $s 
  46.  
  47. fi 
  48.  
  49. done 

12、输入数字运行相应命令

  1. #!/bin/bash 
  2.  
  3. ############################################################## 
  4.  
  5. #输入数字运行相应命令 
  6.  
  7. ############################################################## 
  8.  
  9. echo "*cmd menu* 1-date 2-ls 3-who 4-pwd 0-exit " 
  10.  
  11. while : 
  12.  
  13. do 
  14.  
  15. #捕获用户键入值 
  16.  
  17. read -p "please input number :" n 
  18.  
  19. n1=`echo $n|sed s'/[0-9]//'g` 
  20.  
  21. #空输入检测 
  22.  
  23. if [ -z "$n" ] 
  24.  
  25. then 
  26.  
  27. continue 
  28.  
  29. fi 
  30.  
  31. #非数字输入检测 
  32.  
  33. if [ -n "$n1" ] 
  34.  
  35. then 
  36.  
  37. exit 0 
  38.  
  39. fi 
  40.  
  41. break 
  42.  
  43. done 
  44.  
  45. case $n in 
  46.  
  47. 1
  48.  
  49. date 
  50.  
  51. ;; 
  52.  
  53. 2
  54.  
  55. ls 
  56.  
  57. ;; 
  58.  
  59. 3
  60.  
  61. who 
  62.  
  63. ;; 
  64.  
  65. 4
  66.  
  67. pwd 
  68.  
  69. ;; 
  70.  
  71. 0
  72.  
  73. break 
  74.  
  75. ;; 
  76.  
  77. #输入数字非1-4的提示 
  78.  
  79. *) 
  80.  
  81. echo "please input number is [1-4]" 
  82.  
  83. esac 

13、Expect 实现 SSH 免交互执行命令

Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。

需先安装expect软件包。

  1. 方法1:EOF标准输出作为expect标准输入 
  2.  
  3. #!/bin/bash 
  4.  
  5. USER=root 
  6.  
  7. PASS=123.com 
  8.  
  9. IP=192.168.1.120 
  10.  
  11. expect << EOFset timeout 30spawn ssh $USER@$IP expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "$PASS\r"
  12.  
  13.  
  14. expect "$USER@*" {send "$1\r"
  15.  
  16. expect "$USER@*" {send "exit\r"
  17.  
  18. expect eof 
  19.  
  20. EOF 
  21.  
  22. 方法2: 
  23.  
  24. #!/bin/bash 
  25.  
  26. USER=root 
  27.  
  28. PASS=123.com 
  29.  
  30. IP=192.168.1.120 
  31.  
  32. expect -c " 
  33.  
  34. spawn ssh $USER@$IP 
  35.  
  36. expect { 
  37.  
  38. \"(yes/no)\" {send \"yes\r\"; exp_continue} 
  39.  
  40. \"password:\" {send \"$PASS\r\"; exp_continue} 
  41.  
  42. \"$USER@*\" {send \"df -h\r exit\r\"; exp_continue} 
  43.  
  44. }" 
  45.  
  46. 方法3:将expect脚本独立出来 
  47.  
  48. 登录脚本: 
  49.  
  50. # cat login.exp 
  51.  
  52. #!/usr/bin/expect 
  53.  
  54. set ip [lindex $argv 0
  55.  
  56. set user [lindex $argv 1
  57.  
  58. set passwd [lindex $argv 2
  59.  
  60. set cmd [lindex $argv 3
  61.  
  62. if { $argc != 4 } { 
  63.  
  64. puts "Usage: expect login.exp ip user passwd" 
  65.  
  66. exit 1 
  67.  
  68.  
  69. set timeout 30 
  70.  
  71. spawn ssh $user@$ip 
  72.  
  73. expect { 
  74.  
  75. "(yes/no)" {send "yes\r"; exp_continue} 
  76.  
  77. "password:" {send "$passwd\r"
  78.  
  79.  
  80. expect "$user@*" {send "$cmd\r"
  81.  
  82. expect "$user@*" {send "exit\r"
  83.  
  84. expect eof 
  85.  
  86. 执行命令脚本:写个循环可以批量操作多台服务器 
  87.  
  88. #!/bin/bash 
  89.  
  90. HOST_INFO=user_info.txt 
  91.  
  92. for ip in $(awk '{print $1}' $HOST_INFO) 
  93.  
  94. do 
  95.  
  96. user=$(awk -v I="$ip" 'I==$1{print $2}' $HOST_INFO) 
  97.  
  98. pass=$(awk -v I="$ip" 'I==$1{print $3}' $HOST_INFO) 
  99.  
  100. expect login.exp $ip $user $pass $1 
  101.  
  102. done 
  103.  
  104. Linux主机SSH连接信息: 
  105.  
  106. # cat user_info.txt 
  107.  
  108. 192.168.1.120 root 123456 
  109.  
  110. 创建10个用户,并分别设置密码,密码要求10位且包含大小写字母以及数字,最后需要把每个用户的密码存在指定文件中 
  111.  
  112. #!/bin/bash 
  113.  
  114. ############################################################## 

创建10个用户,并分别设置密码,密码要求10位且包含大小写字母以及数字

  1. #最后需要把每个用户的密码存在指定文件中#前提条件:安装mkpasswd命令 
  2.  
  3. ############################################################## 
  4.  
  5. #生成10个用户的序列(00-09) 
  6.  
  7. for u in `seq -w 0 09`do 
  8.  
  9. #创建用户 
  10.  
  11. useradd user_$u 
  12.  
  13. #生成密码 
  14.  
  15. p=`mkpasswd -s 0 -l 10
  16.  
  17. #从标准输入中读取密码进行修改(不安全) 
  18.  
  19. echo $p|passwd --stdin user_$u 
  20.  
  21. #常规修改密码 
  22.  
  23. echo -e "$p\n$p"|passwd user_$u 
  24.  
  25. #将创建的用户及对应的密码记录到日志文件中 
  26.  
  27. echo "user_$u $p" >> /tmp/userpassworddone 

14、监控 httpd 的进程数,根据监控情况做相应处理

  1. #!/bin/bash 
  2.  
  3. ############################################################################################################################### 
  4.  
  5. #需求: 
  6.  
  7. #1.每隔10s监控httpd的进程数,若进程数大于等于500,则自动重启Apache服务,并检测服务是否重启成功 
  8.  
  9. #2.若未成功则需要再次启动,若重启5次依旧没有成功,则向管理员发送告警邮件,并退出检测 
  10.  
  11. #3.如果启动成功,则等待1分钟后再次检测httpd进程数,若进程数正常,则恢复正常检测(10s一次),否则放弃重启并向管理员发送告警邮件,并退出检测 
  12.  
  13. ############################################################################################################################### 
  14.  
  15. #计数器函数 
  16.  
  17. check_service() 
  18.  
  19.  
  20. j=0 
  21.  
  22. for i in `seq 1 5
  23.  
  24. do 
  25.  
  26. #重启Apache的命令 
  27.  
  28. /usr/local/apache2/bin/apachectl restart 2> /var/log/httpderr.log 
  29.  
  30. #判断服务是否重启成功 
  31.  
  32. if [ $? -eq 0 ] then 
  33.  
  34. break 
  35.  
  36. else 
  37.  
  38. j=$[$j+1] fi 
  39.  
  40. #判断服务是否已尝试重启5次 
  41.  
  42. if [ $j -eq 5 ] then 
  43.  
  44. mail.py exit 
  45.  
  46. fi 
  47.  
  48. done }while :do 
  49.  
  50. n=`pgrep -l httpd|wc -l` 
  51.  
  52. #判断httpd服务进程数是否超过500 
  53.  
  54. if [ $n -gt 500 ] then 
  55.  
  56. /usr/local/apache2/bin/apachectl restart 
  57.  
  58. if [ $? -ne 0 ] 
  59.  
  60. then 
  61.  
  62. check_service 
  63.  
  64. else 
  65.  
  66. sleep 60 
  67.  
  68. n2=`pgrep -l httpd|wc -l` 
  69.  
  70. #判断重启后是否依旧超过500 
  71.  
  72. if [ $n2 -gt 500 ] 
  73.  
  74. then 
  75.  
  76. mail.py exit 
  77.  
  78. fi 
  79.  
  80. fi 
  81.  
  82. fi 
  83.  
  84. #每隔10s检测一次 
  85.  
  86. sleep 10done 

15、批量修改服务器用户密码

Linux主机SSH连接信息:旧密码

  1. # cat old_pass.txt 
  2.  
  3. 192.168.18.217 root 123456 22 
  4.  
  5. 192.168.18.218 root 123456 22 
  6.  
  7. 内容格式:IP User Password Port 
  8.  
  9. SSH远程修改密码脚本:新密码随机生成 
  10.  
  11. https://www.linuxprobe.com/books 
  12.  
  13. #!/bin/bash 
  14.  
  15. OLD_INFO=old_pass.txt 
  16.  
  17. NEW_INFO=new_pass.txt 
  18.  
  19. for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do 
  20.  
  21. USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO) 
  22.  
  23. PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO) 
  24.  
  25. PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO) 
  26.  
  27. NEW_PASS=$(mkpasswd -l 8) # 随机密码 
  28.  
  29. echo "$IP $USER $NEW_PASS $PORT" >> $NEW_INFO 
  30.  
  31. expect -c " 
  32.  
  33. spawn ssh -p$PORT $USER@$IP 
  34.  
  35. set timeout 2 
  36.  
  37. expect { 
  38.  
  39. \"(yes/no)\" {send \"yes\r\";exp_continue} 
  40.  
  41. \"password:\" {send \"$PASS\r\";exp_continue} 
  42.  
  43. \"$USER@*\" {send \"echo \'$NEW_PASS\' |passwd --stdin $USER\r exit\r\";exp_continue} 
  44.  
  45. }" 
  46.  
  47. done 
  48.  
  49. 生成新密码文件: 
  50.  
  51. # cat new_pass.txt 
  52.  
  53. 192.168.18.217 root n8wX3mU% 22 
  54.  
  55. 192.168.18.218 root c87;ZnnL 22 

16、iptables 自动屏蔽访问网站频繁的IP

场景:恶意访问,安全防范

1)屏蔽每分钟访问超过200的IP

  1. 方法1:根据访问日志(Nginx为例) 
  2.  
  3. #!/bin/bash 
  4.  
  5. DATE=$(date +%d/%b/%Y:%H:%M) 
  6.  
  7. ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}'
  8.  
  9. #先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。 
  10.  
  11. for IP in $ABNORMAL_IP; do 
  12.  
  13. if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then 
  14.  
  15. iptables -I INPUT -s $IP -j DROP fidone 
  16.  
  17. 方法2:通过TCP建立的连接 
  18.  
  19. #!/bin/bash 
  20.  
  21. ABNORMAL_IP=$(netstat -an |awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}'
  22.  
  23. #gsub是将第五列(客户端IP)的冒号和端口去掉 
  24.  
  25. for IP in $ABNORMAL_IP; do 
  26.  
  27. if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then 
  28.  
  29. iptables -I INPUT -s $IP -j DROP 
  30.  
  31. fi 
  32.  
  33. done 

2)屏蔽每分钟SSH尝试登录超过10次的IP

方法1:通过lastb获取登录状态:

  1. #!/bin/bash 
  2.  
  3. DATE=$(date +"%a %b %e %H:%M") #星期月天时分 %e单数字时显示7,而%d显示07 
  4.  
  5. ABNORMAL_IP=$(lastb |grep "$DATE" |awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}')for IP in $ABNORMAL_IP; do 
  6.  
  7. if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then 
  8.  
  9. iptables -I INPUT -s $IP -j DROP fidone 
  10.  
  11. 方法2:通过日志获取登录状态 
  12.  
  13. #!/bin/bash 
  14.  
  15. DATE=$(date +"%b %d %H"
  16.  
  17. ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')" 
  18.  
  19. for IP in $ABNORMAL_IP; do 
  20.  
  21. if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then 
  22.  
  23. iptables -A INPUT -s $IP -j DROP 
  24.  
  25. echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log 
  26.  
  27. fi 
  28.  
  29. done 

17、根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁

  1. #!/bin/bash 
  2.  
  3. #################################################################################### 
  4.  
  5. #根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁 
  6.  
  7. #################################################################################### 
  8.  
  9. logfile=/data/log/access.log 
  10.  
  11. #显示一分钟前的小时和分钟 
  12.  
  13. d1=`date -d "-1 minute" +%H%M` 
  14.  
  15. d2=`date +%M` 
  16.  
  17. ipt=/sbin/iptables 
  18.  
  19. ips=/tmp/ips.txt 
  20.  
  21. block() 
  22.  
  23.  
  24. #将一分钟前的日志全部过滤出来并提取IP以及统计访问次数 
  25.  
  26. grep '$d1:' $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ips 
  27.  
  28. #利用for循环将次数超过100的IP依次遍历出来并予以封禁 
  29.  
  30. for i in `awk '$1>100 {print $2}' $ips` 
  31.  
  32. do 
  33.  
  34. $ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT 
  35.  
  36. echo "`date +%F-%T` $i" >> /tmp/badip.log 
  37.  
  38. done 
  39.  
  40.  
  41. unblock() 
  42.  
  43.  
  44. #将封禁后所产生的pkts数量小于10的IP依次遍历予以解封 
  45.  
  46. for a in `$ipt -nvL INPUT --line-numbers |grep '0.0.0.0/0'|awk '$2<10 {print $1}'|sort -nr` 
  47.  
  48. do 
  49.  
  50. $ipt -D INPUT $a 
  51.  
  52. done 
  53.  
  54. $ipt -Z 
  55.  
  56.  
  57. #当时间在00分以及30分时执行解封函数 
  58.  
  59. if [ $d2 -eq "00" ] || [ $d2 -eq "30" ] 
  60.  
  61. then 
  62.  
  63. #要先解再封,因为刚刚封禁时产生的pkts数量很少 
  64.  
  65. unblock 
  66.  
  67. block 
  68.  
  69. else 
  70.  
  71. block 
  72.  
  73. fi 

18、判断用户输入的是否为IP地址

  1. 方法1
  2.  
  3. #!/bin/bash 
  4.  
  5. function check_ip(){ 
  6.  
  7. IP=$1 
  8.  
  9. VALID_CHECK=$(echo $IP|awk -F. '$1< =255&&$2<=255&&$3<=255&&$4<=255{print "yes"}'
  10.  
  11. if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then 
  12.  
  13. if [ $VALID_CHECK == "yes" ]; then 
  14.  
  15. echo "$IP available." 
  16.  
  17. else 
  18.  
  19. echo "$IP not available!" 
  20.  
  21. fi 
  22.  
  23. else 
  24.  
  25. echo "Format error!" 
  26.  
  27. fi 
  28.  
  29.  
  30. check_ip 192.168.1.1 
  31.  
  32. check_ip 256.1.1.1 
  33.  
  34. 方法2: 
  35.  
  36. #!/bin/bash 
  37.  
  38. function check_ip(){ 
  39.  
  40. IP=$1 
  41.  
  42. if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then 
  43.  
  44. FIELD1=$(echo $IP|cut -d. -f1) 
  45.  
  46. FIELD2=$(echo $IP|cut -d. -f2) 
  47.  
  48. FIELD3=$(echo $IP|cut -d. -f3) 
  49.  
  50. FIELD4=$(echo $IP|cut -d. -f4) 
  51.  
  52. if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ]; then 
  53.  
  54. echo "$IP available." 
  55.  
  56. else 
  57.  
  58. echo "$IP not available!" 
  59.  
  60. fi 
  61.  
  62. else 
  63.  
  64. echo "Format error!" 
  65.  
  66. fi 
  67.  
  68.  
  69. check_ip 192.168.1.1 
  70.  
  71. check_ip 256.1.1.1 
  72.  
  73. 增加版: 
  74.  
  75. 加个死循环,如果IP可用就退出,不可用提示继续输入,并使用awk判断。 
  76.  
  77. #!/bin/bash 
  78.  
  79. function check_ip(){ 
  80.  
  81. local IP=$1 
  82.  
  83. VALID_CHECK=$(echo $IP|awk -F. '$1< =255&&$2<=255&&$3<=255&&$4<=255{print "yes"}'
  84.  
  85. if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then 
  86.  
  87. if [ $VALID_CHECK == "yes" ]; then 
  88.  
  89. return 0 
  90.  
  91. else 
  92.  
  93. echo "$IP not available!" 
  94.  
  95. return 1 
  96.  
  97. fi 
  98.  
  99. else 
  100.  
  101. echo "Format error! Please input again." 
  102.  
  103. return 1 
  104.  
  105. fi 
  106.  
  107.  
  108. while truedo 
  109.  
  110. read -p "Please enter IP: " IP 
  111.  
  112. check_ip $IP 
  113.  
  114. [ $? -eq 0 ] && break || continue 
  115.  
  116. done 

 

 

责任编辑:张燕妮 来源: 高效运维
相关推荐

2018-03-31 23:18:35

2021-08-31 15:53:48

Nuxt 开箱服务

2022-06-24 10:02:43

PythonShell脚本

2023-01-15 20:28:32

前端图片压缩

2011-04-14 14:55:02

超云云计算

2019-11-25 00:00:00

开源技术 数据

2021-09-26 05:41:47

基础设施连接无线技术网络

2023-03-08 21:25:58

开源工具库开箱

2023-11-04 12:43:44

前端图片参数

2022-08-08 08:29:55

图片压缩前端互联网

2022-02-08 11:03:49

ShellLinux脚本

2024-02-23 18:17:57

Python脚本开发

2017-01-09 13:21:24

达沃超融合

2019-10-31 08:22:39

shell脚本Linux

2021-04-11 07:56:42

ShellLinux

2021-09-01 17:43:32

StreamNativ开源

2021-04-15 11:21:26

Shell脚本Linux

2019-08-13 11:53:01

脚本语言AWKBash

2019-05-21 15:28:00

Tomcat脚本权限
点赞
收藏

51CTO技术栈公众号