Linux运维常用shell脚本之系统管理实例

2022-12-21 18:09:54 浏览数 (1)

1、选择SSH连接主机

写一个配置文件保存被监控主机SSH连接信息,文件内容格式:主机名 IP User Port

代码语言:javascript复制
#!/bin/bash
PS3="Please input number: "
HOST_FILE=host
while true; do
    select NAME in $(awk '{print $1}' $HOST_FILE) quit; do
        [ ${NAME:=empty} == "quit" ] && exit 0
        IP=$(awk -v NAME=${NAME} '$1==NAME{print $2}' $HOST_FILE)
        USER=$(awk -v NAME=${NAME} '$1==NAME{print $3}' $HOST_FILE)
        PORT=$(awk -v NAME=${NAME} '$1==NAME{print $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

2、屏蔽每分钟SSH暴力破解超过10次的IP

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

代码语言:javascript复制
DATE=$(date  "%a %b %e %H:%M") #星期月天时分  %e单数字时显示7,而%d显示07
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
    fi
done

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

代码语言:javascript复制
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

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

需要先安装expect工具。

expect涉及用法说明:

命令描述

set可以设置超时,也可以设置变量

timeout超时等待时间,默认10s

spawn执行一个命令

expect ""匹配输出的内容

exp_continue继续执行下面匹配

r回车

$argc统计位置参数数量

[lindex $argv 0]位置参数

puts打印字符串,类似于echo

expect{...}输入多行记录

方法1:EOF标准输出作为expect标准输入

#!/bin/bash

USER=root

PASS=123.com

IP=192.168.1.120

expect << EOF

set timeout 30

spawn ssh USER@IP   

expect {

"(yes/no)" {send "yesr"; exp_continue}

"password:" {send "$PASSr"}

}

expect "

expect "$USER@*" {send "exitr"}

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 "yesr"; exp_continue}

"password:" {send "$PASSr"; exp_continue}

"$USER@*" {send "df -hr exitr"; exp_continue}

}"

方法3:将expect脚本独立出来

login.exp登录文件:

#!/usr/bin/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 "yesr"; exp_continue}

"password:" {send "$passwdr"}

}

expect "

expect "$user@*" {send "exitr"}

expect eof

执行命令脚本:

代码语言:javascript复制
#!/bin/bash

HOST_INFO=user_info

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

SSH连接信息文件:

# cat user_info 

192.168.1.120 root 123456

4、监控CPU利用率

借助vmstat工具来分析CPU统计信息。

代码语言:javascript复制
#!/bin/bash
DATE=$(date  %F" "%H:%M)
IP=$(ifconfig eth0 |awk -F '[ :] ' '/inet addr/{print $4}')  # 只支持CentOS6
MAIL="example@mail.com"
if ! which vmstat &>/dev/null; then
    echo "vmstat command no found, Please install procps package." 
    exit 1
fi
US=$(vmstat |awk 'NR==3{print $13}')
SY=$(vmstat |awk 'NR==3{print $14}')
IDLE=$(vmstat |awk 'NR==3{print $15}')
WAIT=$(vmstat |awk 'NR==3{print $16}')
USE=$(($US $SY))
if [ $USE -ge 50 ]; then
    echo "
    Date: $DATE
    Host: $IP
    Problem: CPU utilization $USE
    " | mail -s "CPU Monitor" $MAIL
fi

5、监控内存利用率 

代码语言:javascript复制
#!/bin/bash
DATE=$(date  %F" "%H:%M)
IP=$(ifconfig eth0 |awk -F '[ :] ' '/inet addr/{print $4}')  
MAIL="example@mail.com"
TOTAL=$(free -m |awk '/Mem/{print $2}')
USE=$(free -m |awk '/Mem/{print $3-$6-$7}')
FREE=$(($TOTAL-$USE))
# 内存小于1G发送报警邮件
if [ $FREE -lt 1024 ]; then
    echo "
    Date: $DATE
    Host: $IP
    Problem: Total=$TOTAL,Use=$USE,Free=$FREE
    " | mail -s "Memory Monitor" $MAIL
fi

6、监控硬盘利用率

代码语言:javascript复制
#!/bin/bash
DATE=$(date  %F" "%H:%M)
IP=$(ifconfig eth0 |awk -F '[ :] ' '/inet addr/{print $4}')  
MAIL="example@mail.com"
TOTAL=$(fdisk -l |awk -F'[: ] ' 'BEGIN{OFS="="}/^Disk /dev/{printf "%s=%sG,",$2,$3}')
PART_USE=$(df -h |awk 'BEGIN{OFS="="}/^/dev/{print $1,int($5),$6}')
for i in $PART_USE; do
    PART=$(echo $i |cut -d"=" -f1)
    USE=$(echo $i |cut -d"=" -f2)
    MOUNT=$(echo $i |cut -d"=" -f3)
    if [ $USE -gt 80 ]; then
        echo "
        Date: $DATE
        Host: $IP
        Total: $TOTAL
        Problem: $PART=$USE($MOUNT)
        " | mail -s "Disk Monitor" $MAIL
    fi
done

7、监控主机分区

监控主机分区使用率大于80%,就发告警邮件。放到crontab里面,每10分钟执行一次。         a、 首先两台机器要建立服务器间的信任关系。         b、脚本:   

代码语言:javascript复制
 #!/bin/bash
                FSMAX="80"
                remote_user='root'
                remote_ip=(IP地址列表)
                 ip_num='0'
                while [ "$ip_num" -le "$(expr ${#remote_ip[@]} -l)"]
                do
                        read_num='1'
                        ssh "$remote_user"@"${remote_ip[$ip_num]}"  df -h > /tmp/diskcheck_tmp
                        grep '^/dev/*'  /tmp/diskcheck_tmp | awk '{print $5}'|sed 's/%//g'  > /tmp/diskcheck_num_tmp
                          while [ "$read_num" -le $(wc -l < /tmp/diskcheck_num_tmp) ]
                            do
                                    size=$(sed -n "$read_num" 'p'  /tmp/diskcheck_num_tmp)
                                            if [ "size" -gt "$FSMAX" ]
                                            then
                                                    $(grep '^/dev/*'  /tmp/diskcheck_tmp |sed -n $read_num'p'  > /tmp/disk_check_mail)
                                                    $(echo ${remote_ip[$ip_num]}) >> /tmp/disk_check_mail)
                                                    $(mail  -s "diskcheck_alert"  admin  <  /tmp/disk_check_mail)
                                            fi
                                    read_num=$(expr  $read_num   1)
                            done
                        ip_num=$(expr  $ip_num   1)
              done

 ===================写入crontab=====================                 0/10 * * * *   /home/diskcheck.sh   2&>1

8、监控主机磁盘空间

监控主机的磁盘空间,当使用空间超过90%就通过发mail来发警告

代码语言:javascript复制
#!/bin/bash
#monitor available disk space
#提取本服务器的IP地址信息  
IP=`ifconfig eth0 | grep "inet addr" | cut -f 2 -d ":" | cut -f 1 -d " "`    
SPACE=` df -hP | awk '{print int($5)}'`
if [ $SPACE -ge 90 ]
then
  echo "$IP 服务器 磁盘空间 使用率已经超过90%,请及时处理。"|mail -s "$IP 服务器硬盘告警"   fty89@163.com
fi

9、批量主机磁盘利用率监控

前提监控端和被监控端SSH免交互登录或者密钥登录。

写一个配置文件保存被监控主机SSH连接信息,文件内容格式:IP User Port

代码语言:javascript复制
#!/bin/bash
HOST_INFO=host.info
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO); do
    USER=$(awk -v ip=$IP 'ip==$1{print $2}' $HOST_INFO)
    PORT=$(awk -v ip=$IP 'ip==$1{print $3}' $HOST_INFO)
    TMP_FILE=/tmp/disk.tmp
    ssh -p $PORT $USER@$IP 'df -h' > $TMP_FILE
    USE_RATE_LIST=$(awk 'BEGIN{OFS="="}/^/dev/{print $1,int($5)}' $TMP_FILE)
    for USE_RATE in $USE_RATE_LIST; do
        PART_NAME=${USE_RATE%=*}
        USE_RATE=${USE_RATE#*=}
        if [ $USE_RATE -ge 80 ]; then
            echo "Warning: $PART_NAME Partition usage $USE_RATE%!"
        fi
    done
done

10、检查主机是否存活

代码语言:javascript复制
#!/bin/bash
if ping -c 1 192.168.1.1 >/dev/null;then 
        echo "OK."
else 
        echo "NO!"
fi

方法1:将错误IP放到数组里面判断是否ping失败三次

代码语言:javascript复制
#!/bin/bash  

IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"

for IP in $IP_LIST; do

    NUM=1

    while [ $NUM -le 3 ]; do

        if ping -c 1 $IP > /dev/null; then

            echo "$IP Ping is successful."

            break

        else

            # echo "$IP Ping is failure $NUM"

            FAIL_COUNT[$NUM]=$IP

            let NUM  

        fi

    done

    if [ ${#FAIL_COUNT[*]} -eq 3 ];then

        echo "${FAIL_COUNT[1]} Ping is failure!"

        unset FAIL_COUNT[*]

    fi

done

方法2:将错误次数放到FAIL_COUNT变量里面判断是否ping失败三次

代码语言:javascript复制
#!/bin/bash  

IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"

for IP in $IP_LIST; do

    FAIL_COUNT=0

    for ((i=1;i<=3;i  )); do

        if ping -c 1 $IP >/dev/null; then

            echo "$IP Ping is successful."

            break

        else

            # echo "$IP Ping is failure $i"

            let FAIL_COUNT  

        fi

    done

    if [ $FAIL_COUNT -eq 3 ]; then

        echo "$IP Ping is failure!"

    fi

done

方法3:利用for循环将ping通就跳出循环继续,如果不跳出就会走到打印ping失败

代码语言:javascript复制
#!/bin/bash

ping_success_status() {

    if ping -c 1 $IP >/dev/null; then

        echo "$IP Ping is successful."

        continue

    fi

}

IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2"

for IP in $IP_LIST; do

    ping_success_status

    ping_success_status

    ping_success_status

    echo "$IP Ping is failure!"

done

11、检查多个主机是否存活

代码语言:javascript复制
#!/bin/bash
if ping -c 1 192.168.1.1 >/dev/null;then 
        echo "OK."
else
        echo "NO!"
fi

11、getopts工具完善脚本命令行参数

getopts是一个解析脚本选项参数的工具。

命令格式:getopts optstring name [arg]

初次使用你要注意这几点:

1)脚本位置参数会与optstring中的单个字母逐个匹配,如果匹配到就赋值给name,否则赋值name为问号;

2)optstring中单个字母是一个选项,如果字母后面加冒号,表示该选项后面带参数,参数值并会赋值给OPTARG变量;

3)optstring中第一个是冒号,表示屏蔽系统错误(test.sh: illegal option -- h);

4)允许把选项放一起,例如-ab

下面写一个打印文件指定行的简单例子,用于引导你思路,扩展你的脚本选项功能:

代码语言:javascript复制
#!/bin/bash

while getopts :f:n: option; do

    case $option in 

        f)

            FILE=$OPTARG

        [ ! -f $FILE ] && echo "$FILE File not exist!" && exit

            ;;

        n)

            sed -n "${OPTARG}p" $FILE

            ;;

        ?)

            echo "Usage: $0 -f <file_path> -n <line_number>"

            echo "-f, --file           specified file"

            echo "-n, --line-number    print specified line"

            exit 1

        ;;

    esac

done
代码语言:javascript复制
#!/bin/bash
# 获取要监控的本地服务器IP地址
IP=`ifconfig eth0 | grep "inet addr" | cut -f 2 -d ":" | cut -f 1 -d " "`
echo "IP地址:"$IP

# 获取cpu总核数
cpu_num=`grep -c "model name" /proc/cpuinfo`
echo "cpu总核数:"$cpu_num

# 1、获取CPU利用率
# 获取用户空间占用CPU百分比
cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2}' | cut -f 1 -d "%"`
echo "用户空间占用CPU百分比:"$cpu_user

# 获取内核空间占用CPU百分比
cpu_system=`top -b -n 1 | grep Cpu | awk '{print $3}' | cut -f 1 -d "%"`
echo "内核空间占用CPU百分比:"$cpu_system

# 获取空闲CPU百分比
cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $5}' | cut -f 1 -d "%"`
echo "空闲CPU百分比:"$cpu_idle

# 获取等待输入输出占CPU百分比
cpu_iowait=`top -b -n 1 | grep Cpu | awk '{print $3}' | cut -f 1 -d "%"`
echo "等待输入输出占CPU百分比:"$cpu_iowait

#2、获取CPU上下文切换和中断次数
# 获取CPU中断次数
cpu_interrupt=`vmstat -n 1 1 | sed -n 3p | awk '{print $11}'`
echo "CPU中断次数:"$cpu_interrupt

# 获取CPU上下文切换次数
cpu_context_switch=`vmstat -n 1 1 | sed -n 3p | awk '{print $12}'`
echo "CPU上下文切换次数:"$cpu_context_switch

#3、获取CPU负载信息
# 获取CPU15分钟前到现在的负载平均值
cpu_load_15min=`uptime | awk '{print $11}' | cut -f 1 -d ','`
echo "CPU 15分钟前到现在的负载平均值:"$cpu_load_15min

# 获取CPU5分钟前到现在的负载平均值
cpu_load_5min=`uptime | awk '{print $10}' | cut -f 1 -d ','`
echo "CPU 5分钟前到现在的负载平均值:"$cpu_load_5min

# 获取CPU1分钟前到现在的负载平均值
cpu_load_1min=`uptime | awk '{print $9}' | cut -f 1 -d ','`
echo "CPU 1分钟前到现在的负载平均值:"$cpu_load_1min

# 获取任务队列(就绪状态等待的进程数)
cpu_task_length=`vmstat -n 1 1 | sed -n 3p | awk '{print $1}'`
echo "CPU任务队列长度:"$cpu_task_length

#4、获取内存信息
# 获取物理内存总量
mem_total=`free | grep Mem | awk '{print $2}'`
echo "物理内存总量:"$mem_total

# 获取操作系统已使用内存总量
mem_sys_used=`free | grep Mem | awk '{print $3}'`
echo "已使用内存总量(操作系统):"$mem_sys_used

# 获取操作系统未使用内存总量
mem_sys_free=`free | grep Mem | awk '{print $4}'`
echo "剩余内存总量(操作系统):"$mem_sys_free

# 获取应用程序已使用的内存总量
mem_user_used=`free | sed -n 3p | awk '{print $3}'`
echo "已使用内存总量(应用程序):"$mem_user_used

# 获取应用程序未使用内存总量
mem_user_free=`free | sed -n 3p | awk '{print $4}'`
echo "剩余内存总量(应用程序):"$mem_user_free


# 获取交换分区总大小
mem_swap_total=`free | grep Swap | awk '{print $2}'`
echo "交换分区总大小:"$mem_swap_total

# 获取已使用交换分区大小
mem_swap_used=`free | grep Swap | awk '{print $3}'`
echo "已使用交换分区大小:"$mem_swap_used

# 获取剩余交换分区大小
mem_swap_free=`free | grep Swap | awk '{print $4}'`
echo "剩余交换分区大小:"$mem_swap_free

#5、获取磁盘I/O统计信息
echo "指定设备(/dev/sda)的统计信息"
# 每秒向设备发起的读请求次数
disk_sda_rs=`iostat -kx | grep sda| awk '{print $4}'`
echo "每秒向设备发起的读请求次数:"$disk_sda_rs

# 每秒向设备发起的写请求次数
disk_sda_ws=`iostat -kx | grep sda| awk '{print $5}'`
echo "每秒向设备发起的写请求次数:"$disk_sda_ws

# 向设备发起的I/O请求队列长度平均值
disk_sda_avgqu_sz=`iostat -kx | grep sda| awk '{print $9}'`
echo "向设备发起的I/O请求队列长度平均值"$disk_sda_avgqu_sz

# 每次向设备发起的I/O请求平均时间
disk_sda_await=`iostat -kx | grep sda| awk '{print $10}'`
echo "每次向设备发起的I/O请求平均时间:"$disk_sda_await

# 向设备发起的I/O服务时间均值
disk_sda_svctm=`iostat -kx | grep sda| awk '{print $11}'`
echo "向设备发起的I/O服务时间均值:"$disk_sda_svctm

# 向设备发起I/O请求的CPU时间百分占比
disk_sda_util=`iostat -kx | grep sda| awk '{print $12}'`
echo "向设备发起I/O请求的CPU时间百分占比:"$disk_sda_util

0 人点赞