30个经典shell脚本(中)

Posted zjz20

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了30个经典shell脚本(中)相关的知识,希望对你有一定的参考价值。

注:转自https://weibo.com/ttarticle/p/show?id=2309404415113397403767#_0(刘遄老师的Linux就该这样学)

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

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

13、判断用户输入的是否为数字

14、给定目录找出包含关键字的文件

15、监控目录,将新创建的文件名追加到日志中

16、给用户提供多个网卡选择

17、查看网卡实时流量

18、mysql数据库备份

19、nginx服务管理脚本

20、用户根据菜单选择要连接的Linux主机


 

11、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]++ENDfor(i in a)if(a[i]>100)print i‘)

#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。

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:通过TCP建立的连接

#!/bin/bash

ABNORMAL_IP=$(netstat -an |awk ‘$4~/:80$/ && $6~/ESTABLISHED/gsub(/:[0-9]+/,"",$5);a[$5]++ENDfor(i in a)if(a[i]>100)print i‘)

#gsub是将第五列(客户端IP)的冒号和端口去掉

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") #星期月天时分 %e单数字时显示7,而%d显示07

ABNORMAL_IP=$(lastb |grep "$DATE" |awk ‘a[$3]++ENDfor(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

fi

done

方法2:通过日志获取登录状态

#!/bin/bash

DATE=$(date +"%b %d %H")

ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk ‘/Failed/a[$(NF-3)]++ENDfor(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

 

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

方法1:

#!/bin/bash

function check_ip()

IP=$1

VALID_CHECK=$(echo $IP|awk -F. ‘$1< =255&&$2<=255&&$3<=255&&$4<=255print "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<=255print "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

 

13、判断用户输入的是否为数字

方法1:

#!/bin/bash

if [[ $1 =~ ^[0-9]+$ ]]; then

echo "Is Number."

else

echo "No Number."

fi

 

方法2:

#!/bin/bash

if [ $1 -gt 0 ] 2>/dev/null; then

echo "Is Number."

else

echo "No Number."

fi

 

方法3:

#!/bin/bash

echo $1 |awk ‘print $0~/^[0-9]+$/?"Is Number.":"No Number."‘ #三目运算符

12.14 找出包含关键字的文件

DIR=$1

KEY=$2

for FILE in $(find $DIR -type f); do

if grep $KEY $FILE &>/dev/null; then

echo "--> $FILE"

fi

done

 

14、给定目录找出包含关键字的文件

#!/bin/bash

DIR=$1

KEY=$2

for FILE in $(find $DIR -type f); do

if grep $KEY $FILE &>/dev/null; then

echo "--> $FILE"

fi

done

 

15、监控目录,将新创建的文件名追加到日志中

场景:记录目录下文件操作。

需先安装inotify-tools软件包。

#!/bin/bash

MON_DIR=/opt

inotifywait -mq --format %f -e create $MON_DIR |\

while read files; do

echo $files >> test.log

done

 

16、给用户提供多个网卡选择

场景:服务器多个网卡时,获取指定网卡,例如网卡流量

#!/bin/bash

function local_nic()

local NUM ARRAY_LENGTH

NUM=0

for NIC_NAME in $(ls /sys/class/net|grep -vE "lo|docker0"); do

NIC_IP=$(ifconfig $NIC_NAME |awk -F‘[: ]+‘ ‘/inet addr/print $4‘)

if [ -n "$NIC_IP" ]; then

NIC_IP_ARRAY[$NUM]="$NIC_NAME:$NIC_IP" #将网卡名和对应IP放到数组

let NUM++

fi

done

ARRAY_LENGTH=$#NIC_IP_ARRAY[*]

if [ $ARRAY_LENGTH -eq 1 ]; then #如果数组里面只有一条记录说明就一个网卡

NIC=$NIC_IP_ARRAY[0]%:*

return 0

elif [ $ARRAY_LENGTH -eq 0 ]; then #如果没有记录说明没有网卡

echo "No available network card!"

exit 1

else

#如果有多条记录则提醒输入选择

for NIC in $NIC_IP_ARRAY[*]; do

echo $NIC

done

while true; do

read -p "Please enter local use to network card name: " INPUT_NIC_NAME

COUNT=0

for NIC in $NIC_IP_ARRAY[*]; do

NIC_NAME=$NIC%:*

if [ $NIC_NAME == "$INPUT_NIC_NAME" ]; then

NIC=$NIC_IP_ARRAY[$COUNT]%:*

return 0

else

COUNT+=1

fi

done

echo "Not match! Please input again."

done

fi

local_nic

 

17、查看网卡实时流量

适用于CentOS6操作系统。

#!/bin/bash

# Description: Only CentOS6

traffic_unit_conv()

local traffic=$1

if [ $traffic -gt 1024000 ]; then

printf "%.1f%s" "$(($traffic/1024/1024))" "MB/s"

elif [ $traffic -lt 1024000 ]; then

printf "%.1f%s" "$(($traffic/1024))" "KB/s"

fi

NIC=$1

echo -e " In ------ Out"

while true; do

OLD_IN=$(awk -F‘[: ]+‘ ‘$0~"‘$NIC‘"print $3‘ /proc/net/dev)

OLD_OUT=$(awk -F‘[: ]+‘ ‘$0~"‘$NIC‘"print $11‘ /proc/net/dev)

sleep 1

NEW_IN=$(awk -F‘[: ]+‘ ‘$0~"‘$NIC‘"print $3‘ /proc/net/dev)

NEW_OUT=$(awk -F‘[: ]+‘ ‘$0~"‘$NIC‘"print $11‘ /proc/net/dev)

IN=$(($NEW_IN-$OLD_IN))

OUT=$(($NEW_OUT-$OLD_OUT))

echo "$(traffic_unit_conv $IN) $(traffic_unit_conv $OUT)"

sleep 1

done

使用:./traffic.sh eth0

 

18、MySQL数据库备份

#!/bin/bash

DATE=$(date +%F_%H-%M-%S)

HOST=192.168.1.120

DB=test

USER=bak

PASS=123456

MAIL="zhangsan@example.com lisi@example.com"

BACKUP_DIR=/data/db_backup

SQL_FILE=$DB_full_$DATE.sql

BAK_FILE=$DB_full_$DATE.zip

cd $BACKUP_DIR

if mysqldump -h$HOST -u$USER -p$PASS --single-transaction --routines --triggers -B $DB > $SQL_FILE; then

zip $BAK_FILE $SQL_FILE && rm -f $SQL_FILE

if [ ! -s $BAK_FILE ]; then

echo "$DATE 内容" | mail -s "主题" $MAIL

fi

else

echo "$DATE 内容" | mail -s "主题" $MAIL

fi

find $BACKUP_DIR -name ‘*.zip‘ -ctime +14 -exec rm \;

 

19、Nginx服务管理脚本

场景:使用源码包安装Nginx不含带服务管理脚本,也就是不能使用"service nginx start"或"/etc/init.d/nginx start",所以写了以下的服务管理脚本。

#!/bin/bash

# Description: Only support RedHat system

. /etc/init.d/functions

WORD_DIR=/usr/local/nginx

DAEMON=$WORD_DIR/sbin/nginx

CONF=$WORD_DIR/conf/nginx.conf

NAME=nginx

PID=$(awk -F‘[; ]+‘ ‘/^[^#]/if($0~/pid;/)print $2‘ $CONF)

if [ -z "$PID" ]; then

PID=$WORD_DIR/logs/nginx.pid

else

PID=$WORD_DIR/$PID

fi

stop()

$DAEMON -s stop

sleep 1

[ ! -f $PID ] && action "* Stopping $NAME" /bin/true || action "* Stopping $NAME" /bin/false

start()

$DAEMON

sleep 1

[ -f $PID ] && action "* Starting $NAME" /bin/true || action "* Starting $NAME" /bin/false

reload()

$DAEMON -s reload

test_config()

$DAEMON -t

case "$1" in

start)

if [ ! -f $PID ]; then

start

else

echo "$NAME is running..."

exit 0

fi

;;

stop)

if [ -f $PID ]; then

stop

else

echo "$NAME not running!"

exit 0

fi

;;

restart)

if [ ! -f $PID ]; then

echo "$NAME not running!"

start

else

stop

start

fi

;;

reload)

reload

;;

testconfig)

test_config

;;

status)

[ -f $PID ] && echo "$NAME is running..." || echo "$NAME not running!"

;;

*)

echo "Usage: $0 start|stop|restart|reload|testconfig|status"

exit 3

;;

esac

 

20、用户根据菜单选择要连接的Linux主机

Linux主机SSH连接信息:

# cat host.txt

Web 192.168.1.10 root 22

DB 192.168.1.11 root 22

内容格式:主机名 IP User Port

#!/bin/bash

PS3="Please input number: "

HOST_FILE=host.txt

while true; do

select NAME in $(awk ‘print $1‘ $HOST_FILE) quit; do

[ $NAME:=empty == "quit" ] && exit 0

IP=$(awk -v NAME=$NAME ‘$1==NAMEprint $2‘ $HOST_FILE)

USER=$(awk -v NAME=$NAME ‘$1==NAMEprint $3‘ $HOST_FILE)

PORT=$(awk -v NAME=$NAME ‘$1==NAMEprint $4‘ $HOST_FILE)

if [ $IP ]; then

echo "Name: $NAME, IP: $IP"

ssh -o StrictHostKeyChecking=no -p $PORT -i id_rsa $USER@$IP # 密钥免交互登录

break

else

echo "Input error, Please enter again!"

break

fi

done

done

以上是关于30个经典shell脚本(中)的主要内容,如果未能解决你的问题,请参考以下文章

30个Linux Shell脚本经典案例(中)

30个Linux Shell脚本经典案例(上)

最近练习的一些经典Shell脚本实战30个

shell脚本上

70个经典的 Shell 脚本面试问题

一些经典的 Shell 脚本面试问题 及shell脚本实例