
1、检测两台服务器指定目录下的文件一致性
| #!/bin/bash |
| |
| 检测两台服务器指定目录下的文件一致性 |
| |
| |
| dir=/data/web |
| b_ip=192.168.88.10 |
| |
| find $dir -type f|xargs md5sum > /tmp/md5_a.txt |
| ssh $b_ip "find $dir -type f|xargs md5sum > /tmp/md5_b.txt" |
| scp $b_ip:/tmp/md5_b.txt /tmp |
| |
| for f in `awk '{print 2} /tmp/md5_a.txt'`do |
| |
| if grep -qw "$f" /tmp/md5_b.txt |
| then |
| md5_a=`grep -w "$f" /tmp/md5_a.txt|awk '{print 1}'` |
| md5_b=`grep -w "$f" /tmp/md5_b.txt|awk '{print 1}'` |
| |
| if [ $md5_a != $md5_b ]then |
| echo "$f changed." |
| fi |
| else |
| echo "$f deleted." |
| fi |
| done |
2、定时清空文件内容,定时记录文件大小
| #!/bin/bash |
| |
| 每小时执行一次脚本(任务计划),当时间为0点或12点时,将目标目录下的所有文件内 |
| |
| logfile=/tmp/`date +%H-%F`.log |
| n=`date +%H` |
| if [ $n -eq 00 ] || [ $n -eq 12 ] |
| then |
| |
| for i in `find /data/log/ -type f` |
| do |
| true > $i |
| done |
| else |
| for i in `find /data/log/ -type f` |
| do |
| du -sh $i >> $logfile |
| done |
| fi |
3、检测网卡流量,并按规定格式记录在日志中
| #!/bin/bash |
| |
| |
| |
| |
| |
| |
| |
| while : |
| do |
| |
| LANG=en |
| logfile=/tmp/`date +%d`.log |
| |
| exec >> $logfile |
| date +"%F %H:%M" |
| |
| 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"}' |
| echo "####################" |
| |
| done |
4、计算文档每行出现的数字个数,并计算整个文档的数字总数
| #!/bin/bash |
| |
| |
| |
| |
| n=`wc -l a.txt|awk '{print $1}'` |
| sum=0 |
| |
| for i in `seq 1 $n`do |
| |
| line=`sed -n "$i"p a.txt` |
| n_n=`echo $line|sed s'/[^0-9]//'g|wc -L` |
| echo $n_nsum=$[$sum+$n_n] |
| done |
| echo "sum:$sum" |
杀死所有脚本
| #!/bin/bash |
| |
| |
| |
| |
| ps aux|grep 指定进程名|grep -v grep|awk '{print $2}'|xargs kill -9 |
5、从 FTP 服务器下载文件
| #!/bin/bash |
| if [ $# -ne 1 ]; then |
| echo "Usage: $0 filename" |
| fi |
| dir=$(dirname $1) |
| file=$(basename $1) |
| ftp -n -v << EOF # -n 自动登录 |
| open 192.168.1.10 # ftp服务器 |
| user admin password |
| binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误 |
| cd $dir |
| get "$file" |
| EOF |
6、连续输入5个100以内的数字,统计和、最小和最大
| #!/bin/bash |
| COUNT=1 |
| SUM=0 |
| MIN=0 |
| MAX=100 |
| while [ $COUNT -le 5 ]; do |
| read -p "请输入1-10个整数:" INT |
| if [[ ! $INT =~ ^[0-9]+$ ]]; then |
| echo "输入必须是整数!" |
| exit 1 |
| elif [[ $INT -gt 100 ]]; then |
| echo "输入必须是100以内!" |
| exit 1 |
| fi |
| SUM=$(($SUM+$INT)) |
| [ $MIN -lt $INT ] && MIN=$INT |
| [ $MAX -gt $INT ] && MAX=$INT |
| let COUNT++ |
| done |
| echo "SUM: $SUM" |
| echo "MIN: $MIN" |
| echo "MAX: $MAX |
| |
用户猜数字
| #!/bin/bash # 脚本生成一个 100 以内的随机数,提示用户猜数字,根据用户的输入,提示用户猜对了, |
| |
| |
| |
| |
| |
| |
| |
| while : |
| do |
| read -p "计算机生成了一个 1‐100 的随机数,你猜: " cai |
| if [ $cai -eq $num ] |
| then |
| echo "恭喜,猜对了" |
| exit |
| elif [ $cai -gt $num ] |
| then |
| echo "Oops,猜大了" |
| else |
| echo "Oops,猜小了" |
| fi |
| done |
7、监测 Nginx 访问日志 502 情况,并做相应动作
假设服务器环境为 lnmp,近期访问经常出现 502 现象,且 502 错误在重启 php-fpm 服务后消失,因此需要编写监控脚本,一旦出现 502,则自动重启 php-fpm 服务。
| |
| |
| |
| |
| |
| |
| |
| |
| log=/data/log/access.log |
| N=30 |
| while :do |
| |
| err=`tail -n 300 $log |grep -c '502" '` |
| if [ $err -ge $N ] |
| then |
| /etc/init.d/php-fpm restart 2> /dev/null |
| |
| sleep 60 |
| fi |
| sleep 10 |
| done |
8、将结果分别赋值给变量
应用场景:希望将执行结果或者位置参数赋值给变量,以便后续使用。
方法1:
| for i in $(echo "4 5 6"); do |
| eval a$i=$idone |
| echo $a4 $a5 $a6 |
方法2:将位置参数192.168.1.1{1,2}
拆分为到每个变量
| num=0 |
| for i in $(eval echo $*);do |
| let num+=1 |
| eval node${num}="$i" |
| done |
| echo $node1 $node2 $node3 |
| |
| 192.168.1.11 192.168.1.12 |
| |
| 方法3:arr=(4 5 6) |
| INDEX1=$(echo ${arr[0]}) |
| INDEX2=$(echo ${arr[1]}) |
| INDEX3=$(echo ${arr[2]}) |
9、批量修改文件名
示例:
| # touch article_{1..3}.html |
| # lsarticle_1.html article_2.html article_3.html |
| 目的:把article改为bbs |
方法1:
| for file in $(ls *html); do |
| mv $file bbs_${file#*_} |
| |
| |
方法2:
| for file in $(find . -maxdepth 1 -name "*html"); do |
| mv $file bbs_${file#*_}done |
方法3:
| |
| 把一个文档前五行中包含字母的行删掉,同时删除6到10行包含的所有字母 |
| |
| 1)准备测试文件,文件名为2.txt |
| |
| 第1行1234567不包含字母 |
| 第2行56789BBBBBB |
| 第3行67890CCCCCCCC |
| 第4行78asdfDDDDDDDDD |
| 第5行123456EEEEEEEE |
| 第6行1234567ASDF |
| 第7行56789ASDF |
| 第8行67890ASDF |
| 第9行78asdfADSF |
| 第10行123456AAAA |
| 第11行67890ASDF |
| 第12行78asdfADSF |
| 第13行123456AAAA |
脚本如下:
| #!/bin/bash |
| |
| 把一个文档前五行中包含字母的行删掉,同时删除6到10行包含的所有字母 |
| |
| sed -n '1,5'p 2.txt |sed '/[a-zA-Z]/'d |
| sed -n '6,10'p 2.txt |sed s'/[a-zA-Z]//'g |
| sed -n '11,$'p 2.txt |
| |
10、统计当前目录中以.html结尾的文件总大
方法1:
| |
| |
| 方法2: |
| ```bash |
| for size in $(ls -l *.html |awk '{print $5}'); do |
| sum=$(($sum+$size)) |
| done |
| echo $sum |
11、扫描主机端口状态
| #!/bin/bash |
| HOST=$1 |
| PORT="22 25 80 8080" |
| for PORT in $PORT; do |
| if echo &>/dev/null > /dev/tcp/$HOST/$PORT; then |
| echo "$PORT open" |
| else |
| echo "$PORT close" |
| fi |
| done |
| 用 shell 打印示例语句中字母数小于6的单词 |
| |
| |
| |
| |
| |
| |
| |
| for s in Bash also interprets a number of multi-character options. |
| do |
| n=`echo $s|wc -c` |
| if [ $n -lt 6 ] |
| then |
| echo $s |
| fi |
| done |
12、输入数字运行相应命令
| #!/bin/bash |
| |
| |
| |
| echo "*cmd menu* 1-date 2-ls 3-who 4-pwd 0-exit " |
| while : |
| do |
| |
| read -p "please input number :" n |
| n1=`echo $n|sed s'/[0-9]//'g` |
| |
| if [ -z "$n" ] |
| then |
| continue |
| fi |
| |
| if [ -n "$n1" ] |
| then |
| exit 0 |
| fi |
| break |
| done |
| case $n in |
| 1) |
| date |
| ;; |
| 2) |
| ls |
| ;; |
| 3) |
| who |
| ;; |
| 4) |
| pwd |
| ;; |
| 0) |
| break |
| ;; |
| |
| *) |
| echo "please input number is [1-4]" |
| esac |
13、Expect 实现 SSH 免交互执行命令
Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。
需先安装expect软件包。
方法1:EOF标准输出作为expect标准输入
| #!/bin/bash |
| USER=root |
| PASS=123.com |
| IP=192.168.1.120 |
| expect << EOFset timeout 30spawn ssh $USER@$IP expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "$PASS\r"} |
| } |
| expect "$USER@*" {send "$1\r"} |
| expect "$USER@*" {send "exit\r"} |
| expect eof |
| EOF |
方法2:
| #!/bin/bash |
| USER=root |
| PASS=123.com |
| IP=192.168.1.120 |
| expect -c " |
| spawn ssh $USER@$IP |
| expect { |
| \"(yes/no)\" {send \"yes\r\"; exp_continue} |
| \"password:\" {send \"$PASS\r\"; exp_continue} |
| \"$USER@*\" {send \"df -h\r exit\r\"; exp_continue} |
| }" |
方法3:将expect脚本独立出来
| 登录脚本: |
| |
| |
| set ip [lindex $argv 0] |
| set user [lindex $argv 1] |
| set passwd [lindex $argv 2] |
| set cmd [lindex $argv 3] |
| if { $argc != 4 } { |
| puts "Usage: expect login.exp ip user passwd" |
| exit 1 |
| } |
| set timeout 30 |
| spawn ssh $user@$ip |
| expect { |
| "(yes/no)" {send "yes\r"; exp_continue} |
| "password:" {send "$passwd\r"} |
| } |
| expect "$user@*" {send "$cmd\r"} |
| expect "$user@*" {send "exit\r"} |
| expect eof |
执行命令脚本:写个循环可以批量操作多台服务器
| #!/bin/bash |
| HOST_INFO=user_info.txt |
| for ip in $(awk '{print $1}' $HOST_INFO) |
| do |
| user=$(awk -v I="$ip" 'I==$1{print $2}' $HOST_INFO) |
| pass=$(awk -v I="$ip" 'I==$1{print $3}' $HOST_INFO) |
| expect login.exp $ip $user $pass $1 |
| done |
| Linux主机SSH连接信息: |
| |
| 192.168.1.120 root 123456 |
| 创建10个用户,并分别设置密码,密码要求10位且包含大小写字母以及数字,最后需要把每个用户的密码存在指定文件中 |
| ```bash |
| |
| |
| |
| |
| |
| |
| for u in `seq -w 0 09`do |
| |
| useradd user_$u |
| |
| p=`mkpasswd -s 0 -l 10` |
| |
| echo $p|passwd --stdin user_$u |
| |
| echo -e "$p\n$p"|passwd user_$u |
| |
| echo "user_$u $p" >> /tmp/userpassworddone |
14、监控 httpd 的进程数,根据监控情况做相应处理
| #!/bin/bash |
| |
| |
| |
| |
| |
| |
| |
| check_service() |
| { |
| j=0 |
| for i in `seq 1 5` |
| do |
| |
| /usr/local/apache2/bin/apachectl restart 2> /var/log/httpderr.log |
| |
| if [ $? -eq 0 ] then |
| break |
| else |
| j=$[$j+1] fi |
| |
| if [ $j -eq 5 ] then |
| mail.py exit |
| fi |
| done }while :do |
| n=`pgrep -l httpd|wc -l` |
| |
| if [ $n -gt 500 ] then |
| /usr/local/apache2/bin/apachectl restart |
| if [ $? -ne 0 ] |
| then |
| check_service |
| else |
| sleep 60 |
| n2=`pgrep -l httpd|wc -l` |
| |
| if [ $n2 -gt 500 ] |
| then |
| mail.py exit |
| fi |
| fi |
| fi |
| |
| sleep 10done |
15、批量修改服务器用户密码
Linux主机SSH连接信息:旧密码
| # cat old_pass.txt |
| 192.168.18.217 root 123456 22 |
| 192.168.18.218 root 123456 22 |
| 内容格式:IP User Password Port |
| |
| SSH远程修改密码脚本:新密码随机生成 |
| https: |
| #!/bin/bash |
| OLD_INFO=old_pass.txt |
| NEW_INFO=new_pass.txt |
| for IP in $(awk '/^[^#]/{print $1}' $OLD_INFO); do |
| USER=$(awk -v I=$IP 'I==$1{print $2}' $OLD_INFO) |
| PASS=$(awk -v I=$IP 'I==$1{print $3}' $OLD_INFO) |
| PORT=$(awk -v I=$IP 'I==$1{print $4}' $OLD_INFO) |
| NEW_PASS=$(mkpasswd -l 8) # 随机密码 |
| echo "$IP $USER $NEW_PASS $PORT" >> $NEW_INFO |
| expect -c " |
| spawn ssh -p$PORT $USER@$IP |
| set timeout 2 |
| expect { |
| \"(yes/no)\" {send \"yes\r\";exp_continue} |
| \"password:\" {send \"$PASS\r\";exp_continue} |
| \"$USER@*\" {send \"echo \'$NEW_PASS\' |passwd --stdin $USER\r exit\r\";exp_continue} |
| }" |
| done |
| 生成新密码文件: |
| |
| # cat new_pass.txt |
| 192.168.18.217 root n8wX3mU% 22 |
| 192.168.18.218 root c87;ZnnL 22 |
16、iptables 自动屏蔽访问网站频繁的IP
场景:恶意访问,安全防范
1)屏蔽每分钟访问超过200的IP
方法1:根据访问日志(Nginx为例)
| #!/bin/bash |
| DATE=$(date +%d/%b/%Y:%H:%M) |
| ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}') |
| |
| for IP in $ABNORMAL_IP; do |
| if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then |
| iptables -I INPUT -s $IP -j DROP fidone |
方法2:通过TCP建立的连接
| #!/bin/bash |
| 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}') |
| |
| for IP in $ABNORMAL_IP; do |
| if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then |
| iptables -I INPUT -s $IP -j DROP |
| fi |
| done |
2)屏蔽每分钟SSH尝试登录超过10次的IP
方法1:通过lastb获取登录状态:
| #!/bin/bash |
| DATE=$(date +"%a %b %e %H:%M") |
| 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 |
| if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then |
| iptables -I INPUT -s $IP -j DROP fidone |
方法2:通过日志获取登录状态
| #!/bin/bash |
| DATE=$(date +"%b %d %H") |
| 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}')" |
| for IP in $ABNORMAL_IP; do |
| if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then |
| iptables -A INPUT -s $IP -j DROP |
| echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log |
| fi |
| done |
17、根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
| #!/bin/bash |
| |
| |
| |
| logfile=/data/log/access.log |
| |
| d1=`date -d "-1 minute" +%H%M` |
| d2=`date +%M` |
| ipt=/sbin/iptables |
| ips=/tmp/ips.txt |
| block() |
| { |
| |
| grep '$d1:' $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ips |
| |
| for i in `awk '$1>100 {print $2}' $ips` |
| do |
| $ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT |
| echo "`date +%F-%T` $i" >> /tmp/badip.log |
| done |
| } |
| unblock() |
| { |
| |
| for a in `$ipt -nvL INPUT --line-numbers |grep '0.0.0.0/0'|awk '$2<10 {print $1}'|sort -nr` |
| do |
| $ipt -D INPUT $a |
| done |
| $ipt -Z |
| } |
| |
| if [ $d2 -eq "00" ] || [ $d2 -eq "30" ] |
| then |
| |
| unblock |
| block |
| else |
| block |
| fi |
18、判断用户输入的是否为IP地址
方法1:
| #!/bin/bash |
| function check_ip(){ |
| IP=$1 |
| VALID_CHECK=$(echo $IP|awk -F. '$1< =255&&$2<=255&&$3<=255&&$4<=255{print "yes"}') |
| if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then |
| if [ $VALID_CHECK == "yes" ]; then |
| echo "$IP available." |
| else |
| echo "$IP not available!" |
| fi |
| else |
| echo "Format error!" |
| fi |
| } |
| check_ip 192.168.1.1 |
| check_ip 256.1.1.1 |
方法2:
| #!/bin/bash |
| function check_ip(){ |
| IP=$1 |
| if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then |
| FIELD1=$(echo $IP|cut -d. -f1) |
| FIELD2=$(echo $IP|cut -d. -f2) |
| FIELD3=$(echo $IP|cut -d. -f3) |
| FIELD4=$(echo $IP|cut -d. -f4) |
| if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ]; then |
| echo "$IP available." |
| else |
| echo "$IP not available!" |
| fi |
| else |
| echo "Format error!" |
| fi |
| } |
| check_ip 192.168.1.1 |
| check_ip 256.1.1.1 |
增加版:
加个死循环,如果IP可用就退出,不可用提示继续输入,并使用awk判断。
| #!/bin/bash |
| function check_ip(){ |
| local IP=$1 |
| VALID_CHECK=$(echo $IP|awk -F. '$1< =255&&$2<=255&&$3<=255&&$4<=255{print "yes"}') |
| if echo $IP|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" >/dev/null; then |
| if [ $VALID_CHECK == "yes" ]; then |
| return 0 |
| else |
| echo "$IP not available!" |
| return 1 |
| fi |
| else |
| echo "Format error! Please input again." |
| return 1 |
| fi |
| } |
| while true; do |
| read -p "Please enter IP: " IP |
| check_ip $IP |
| [ $? -eq 0 ] && break || continue |
| done |