Shell脚本练习——系统应用相关(1)

测试网络状态

[root@wenzi data]#vim ping.sh 
#!/bin/bash
host=$1
ping $host -c5
if [ $? -eq 0 ];then
	echo "Successful"
else
	echo "Failure"
fi
[root@wenzi data]#bash ping.sh 192.168.29.142
PING 192.168.29.142 (192.168.29.142) 56(84) bytes of data.
64 bytes from 192.168.29.142: icmp_seq=1 ttl=64 time=0.396 ms
64 bytes from 192.168.29.142: icmp_seq=2 ttl=64 time=0.573 ms
64 bytes from 192.168.29.142: icmp_seq=3 ttl=64 time=0.286 ms
64 bytes from 192.168.29.142: icmp_seq=4 ttl=64 time=0.516 ms
64 bytes from 192.168.29.142: icmp_seq=5 ttl=64 time=0.412 ms
 
--- 192.168.29.142 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 97ms
rtt min/avg/max/mdev = 0.286/0.436/0.573/0.102 ms
Successful
[root@wenzi wenzi]# cat test.sh
#!/bin/bash
ip_list=$*
for ip in $ip_list;do
        if ping -c 5 $ip > /dev/null;then
                echo "$ip ping is successful"
                continue
        fi
        echo "$ip ping is failure"
done
 
[root@wenzi wenzi]# ./test.sh 127.0.0.1 192.168.28.200
127.0.0.1 ping is successful
192.168.28.200 ping is failure

说明:

$* 表示除了$0以外,所有的参数,如上即 “opt1 opt2 opt3 opt4“,每个变量之间用空格分割,共用一个双引号

检测192.168.28.0/24网段内在线主机的IP地址

#!/bin/bash
ip=192.168.28
 
for i in `seq 1 254`;do
        fullIP=$ip.$i
        ping -c 3 $fullIP &> /dev/null
        if [ $? -eq 0 ];then
                echo "$fullIP"
        fi
done

显示系统信息

[root@wenzi data]#cat systemInfo.sh 
#/bin/bash
RED="\E[1;31m"
GREEN="\E[1;32m"
END="\E[0m"
echo -e  "$GREEN----------------------Host systeminfo--------------------$END"
echo -e  "HOSTNAME:     $RED`hostname`$END"
echo -e  "IPADDR:       $RED`ifconfig ens160 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n 1`$END"
echo -e  "OSVERSION:    $RED`cat /etc/redhat-release`$END"
echo -e  "KERNEL:       $RED`uname -r`$END"
echo -e  "CPU:         $RED`lscpu | grep 'Model name'| tr -s ' ' | cut -d : -f 2`$END"
echo -e  "MEMORY:       $RED`free -h | grep 'Mem' | tr -s ' ' : | cut -d ':' -f 2`$END"
echo -e  "DISK:         $RED`lsblk | grep '^nv' | tr -s ' ' | cut -d " " -f 4`$END"
echo -e  "$GREEN---------------------------------------------------------$END"

说明:

grep -E 开启拓展正则表达式,-o 仅显示匹配到的数据

([0-9]{1,3}\.){3}[0-9]{1,3}中[0-9]{1,3}表示1到3位数字,{3}表示重复3次,所以整体就是匹配IP地址

tr -s 对指定的字符串去重复

cut 使用对象是一行信息,-d 指定分割字符,-f 依据-d的分割字符将一段信息分为数段,用-f取出第几段

^nv 指以nv开头

批量创建用户并设置随机密码

[root@wenzi data]#cat batchCreateUser.sh 
#!/bin/bash
userNum=$1

for ((i=1;i<=${userNum};i+=1))
do
	useradd wenzi$i
	pwd=`cat /dev/urandom | tr -d -c '[:alnum:]' | head -c 12`
	echo $pwd | passwd --stdin wenzi$i &> /dev/null
	echo wenzi$i:$pwd >> /data/user.log
	echo "wenzi$i is created"
done
[root@wenzi data]#bash batchCreateUser.sh 5
wenzi1 is created
wenzi2 is created
wenzi3 is created
wenzi4 is created
wenzi5 is created
[root@wenzi data]#cat /data/user.log 
wenzi1:aBfx6xKXXWXd
wenzi2:zeiXcSdeECga
wenzi3:XXWhxovUy9o1
wenzi4:mk6wF4gqQxbP
wenzi5:YvcHWo6UYQcP

#删除生成的用户
[root@wenzi data]#for i in {1..5};do userdel -r wenzi$i;done
说明:

/dev/urandom是随机数生成器

[:alnum:] 代表英文大小写字符及数字,即 0-9,A-Z,a-z

tr的-d选项:删除信息中指定内容;-c选项:使用指定字符串的补集替换该字符串;所以tr删除的是非'[:alnum:]'的内容

执行远程主机的脚本

#主机192.168.29.142
[root@wenzi ~]#yum -y install httpd
[root@wenzi ~]#vim /var/www/html/hello.sh
#!/bin/bash
echo "hello world"
[root@wenzi ~]#systemctl start httpd

#主机192.168.29.141
[root@wenzi data]#curl http://192.168.29.142/hello.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    31  100    31    0     0  31000      0 --:--:-- --:--:-- --:--:-- 31000
hello world
[root@wenzi data]#curl -s http://192.168.29.142/hello.sh | bash
hello world

rm命令的安全实现

[root@wenzi data]#vim rm.sh 
#!/bin/bash
warning_color="echo -e \E[1;31m"
end="\E[0m"
dir=/tmp/`date +%F%T`
mkdir $dir
mv $* $dir
${warning_color}Move $* to $dir $end
[root@wenzi data]#chmod 777 /data/rm.sh 
[root@wenzi data]#alias rm='/data/rm.sh'
[root@wenzi data]#touch {1..3}.txt
[root@wenzi data]#ll
total 4
-rw-r--r-- 1 root root   0 Jul 22 10:43 1.txt
-rw-r--r-- 1 root root   0 Jul 22 10:43 2.txt
-rw-r--r-- 1 root root   0 Jul 22 10:43 3.txt
-rw-r--r-- 1 root root 138 Jul 22 10:42 rm.sh
[root@wenzi data]#rm *.txt
Move 1.txt 2.txt 3.txt to /tmp/2023-07-2210:45:20 
说明:

$*:位置变量,代表除了$0(脚本本身名字)以外,所有的参数,如上即 “opt1 opt2 opt3 opt4“,每个变量之间用空格分割,共用一个双引号

检查软件包是否安装

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
pkg=$1
rpm -q $1 > /dev/null
if [ $? -eq 0  ];then
        echo "$1 is already installed."
else
        echo "$1 is not installed!"
fi


[root@wenzi wenzi]# ./test.sh httpd
httpd is already installed.
[root@wenzi wenzi]# ./test.sh nginx
nginx is not installed!

检查服务状态

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
if pgrep $1 > /dev/null;then
        echo "$1 is running"
else
        echo "$1 is not running"
fi

[root@wenzi wenzi]# ./test.sh httpd
httpd is running
[root@wenzi wenzi]# ./test.sh nginx
nginx is not running

检查给定的任意一个服务运行状态

只检查服务sshd crond mysqld 中任意一个服务的状态,如果不是这3个中的服务,就提示用户能够检查的服务名并退出脚本;如果服务是运行着的就输出 "服务名 is running",如果服务没有运行就启动服务

#!/bin/bash

read -p "which service: " service

if [ $service != 'sshd' ] && [ $service != 'crond' ] && [ $service != 'mysqld' ];then
        echo "Can only check sshd、crond、mysqld"
        exit
else
        lines=`pgrep $service | wc -l`
        if [ $lines -gt 0 ];then
                echo "$service is running"
        else
                systemctl start $service
        fi
fi

监控CPU利用率

使用vmstat命令分析

具体含义见 vmstat_笔落_惊风雨的博客-CSDN博客

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
dateTime=`date +'%F %T'`
ip=`ifconfig ens160 | awk 'NR==2{print $2}'`
mail="example@mail.com"
if ! which vmstat &> /dev/null;then
        echo "vmstat command not found,Please install procps package"
        exit 1
fi
cpuUS=`vmstat | awk 'NR==3{print $13}'`
cpuSY=`vmstat | awk 'NR==3{print $14}'`
cpuID=`vmstat | awk 'NR==3{print $15}'`
cpuWA=`vmstat | awk 'NR==3{print $16}'`
allUSE=$[$cpuUS+$cpuSY]
#当CPU利用率超过50%时发送邮件
if [ $allUSE -gt 50 ];then
        echo -e "
        Date: $dateTime
        Host: $ip
        Problem: CPU utilization $allUSE
        " mail -s "CPU Monitor" $mail
fi
说明:
查询vmstat来自哪个软件包
[root@wenzi wenzi]# rpm -qf `which vmstat`
procps-ng-3.3.15-6.el8.x86_64

awk的内置变量NR表示awk处理的是第几行数据

使用管道符发送邮件 echo "邮件内容" | mail -s "邮件标题" 接收方

检测CPU剩余百分比

#!/bin/bash

dateTime=`date +'%F-%T'`
cpuResidue=`top -bn 1 | grep "Cpu" | awk -F ',' '{print $4}' | tr -d 'id' | tr -d ' '`
echo "$dateTime cpuResidue is $cpuResidue%"

说明:

top 的 -b 表示以批处理模式操作;-n 表示循环显示的次数。即将输出top的此刻数据

监控内存利用率

[root@wenzi wenzi]# free -m
              total        used        free      shared  buff/cache   available
Mem:            791         181         274           5         335         477
Swap:          2047           0        2047
[root@wenzi wenzi]# cat test.sh
#!/bin/bash
total=`free -m | awk '/Mem/ {print $2}'`
used=`free -m | awk '/Mem/ {print $2-$4-$6}'`
#获取相除的值
memUtilization=$(printf "%4.2f" `echo "scale=2;$used/$total" | bc`)
#获取没有百分号的百分比
memUti=$(printf "%2.0f" `echo "$memUtilization*100" | bc`)
if [ $memUti -gt 0 ];then
        echo "Memory utilization is $memUti%"
fi
说明:

内存利用率计算见 free_笔落_惊风雨的博客-CSDN博客

awk '/Mem/ {print $2}' 表示直接定位到Mem所在行,然后取第二个字符。 /Mem/ 是awk的模式匹配之一,表示匹配包含Mem的行,格式 /正则表达式/ 表示使用通配符的拓展集

printf语法:printf ‘打印格式’ 实际内容。printf "%4.2f" 表示长度为4个字符的具有小数点的字段,其中小数位占2个字符宽度,小数点占1个字符宽度。

echo "scale=2;$used/$total" | bc 表示计算$used除以$total,保留两位小数后的值。bc计算时若值小于1,显示时会省去个位的0。

为了保留个位的0,所以使用printf再次处理。

printf 和 bc 结合使用,写法 $(printf "%4.2f" `echo "scale=2;$used/$total" | bc`)

监控磁盘利用率

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
diskList=`df -h | grep "^/dev/" | sort`
diskListLineNums=`echo $diskList | wc -l`
for i in $diskListLineNums;do
        diskUsed=`echo $diskList | awk '{print $5}' | awk -F '%' '{print $1}'`
        #当使用率达到50告警
        if [ $diskUsed -gt 50 ];then
                dev=`echo $diskList | awk '{print $1}'`
                devSize=`echo $diskList | awk '{print $2}'`
                echo "$dev is used $diskUsed% , Warning!"
        fi
done





[root@centos8 ~]#df -Th | grep "^/dev" | awk '{print $1,$6}'
/dev/mapper/cl-root 5%
/dev/mapper/cl-data 1%
/dev/nvme0n1p1 22%

检测剩余inode

[root@wenzi ~]# df -i
Filesystem      Inodes IUsed   IFree IUse% Mounted on
devtmpfs         97117   376   96741    1% /dev
tmpfs           101311     1  101310    1% /dev/shm
tmpfs           101311   558  100753    1% /run
tmpfs           101311    17  101294    1% /sys/fs/cgroup
/dev/sda3      8912384 38010 8874374    1% /
/dev/sda1        65536   309   65227    1% /boot
tmpfs           101311     5  101306    1% /run/user/0


[root@wenzi wenzi]# vim test.sh
#!/bin/bash
dateTime=`date +'%F-%H-%M-%S'`
iFree=` df -i | grep -v "Filesystem" | awk '{print $4}'`
for i in $iFree;do
        if [ $i -lt 200 ];then
                fileSys=`df -i | grep "$i" | awk '{print $1}'`
                echo "Date: $dateTime $fileSys inode is less than 200"
        fi
done

检查网站可用性

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
check_url() {
        httpCode=`curl -o /dev/null --connect-timeout 3 -s -w "%{http_code}" $1`
        if [ $httpCode -ne 200 ];then
                echo "Warning: $1 is failure!"
        fi
}
check_url $1

说明:

curl中 -o 表示将下载数据写入指定名称的文件中;--connect-timeout 表示最大请求时间;-w 表示在请求结束后打印本次请求的统计数据到标准输出,curl提供很多内置变量,使用 %{变量} 调用,完整的内置变量查看 man curl。

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

[root@wenzi wenzi]# vim test.sh
#!/bin/bash
PS3="Please enter serial number: "
hostFile=/root/wenzi/hostList.txt
select i in `awk '{print $1}' $hostFile`;do
        [ ${i:=quit} == "quit" ] && exit 0
        ip=`awk -v name=${i} '$1==name{print $2}' $hostFile`
        user=`awk -v name=${i} '$1==name{print $3}' $hostFile`
        port=`awk -v name=${i} '$1==name{print $4}' $hostFile`
        if [ -n $IP ];then
                echo "Name: $i, IP: $ip"
                ssh -o StrictHostKeyChecking=no -p $port -i /root/.ssh/id_rsa $user@$ip
                break
        fi
说明:

PS3 是一个预定义的变量,用于指定输入提示符。

select 语句用于创建一个交互式的菜单,并接收用户的选择。不遇到exit或break不会停下。

${i:=quit} 表示 i 没有设定时 i 的值为quit,i 是空字符串时 i 的值为quit,i 已设定为非空字符串时,i 的值不变。在脚本中即输入的序号存在时,才会执行下面的脚本,否则 i 的值为quit,和等号后面的 quit 一致,会执行exit 0,退出脚本。见 认识与学习Bash_笔落_惊风雨的博客-CSDN博客

awk -v name=${i} 表示将外部的$i变量的值传递给awk,awk以变量name接收,此name只在awk内生效,外部无法调用。$1=name是条件判断

扫描主机端口状态

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
read -p "Please enter IP: " ip
while true;do
        read -p "Please enter Port: " port
        if [ $port == "quit" ];then
                break
        fi
        if nc -n -z -w2 $ip $port &> /dev/null;then
                echo "$port is open"
        else
                echo "$port is close"
        fi
done

说明:

借助nc(来自netcat软件包)命令进行检测,-n 表示使用IP地址;-z 表示使用0输入/输出模式,只在扫描通信端口时使用;-w 表示超时秒数

实现SSH登录免交互执行命令

[root@wenzi wenzi]# cat test.sh
#!/bin/bash
ip=192.168.28.141
user=root
passwd=admin
expect << EOF
#设置超时时间
set timeout 10
#开启ssh连接,固定语法
spawn ssh $user@$ip
expect {
        "(yes/no)" {send "yes\r"; exp_continue}
        "password:" {send "$passwd\r"}
}
expect "$user@*" {send "$1\r"}
expect "$user@*" {send "exit\r"}
# expect结束标志,spawn收到eof后会结束之前开启的进程
expect eof
EOF


#需要输入一个参数,计划在远程主机上执行的命令
[root@wenzi wenzi]# ./test.sh pwd
spawn ssh root@192.168.28.141
Last login: Thu Sep  7 19:08:10 2023 from 192.168.28.158
[root@wenzi ~]# pwd
/root
[root@wenzi ~]# exit
logout
Connection to 192.168.28.141 closed.

说明:

需要安装expect软件包;可以模拟用户在终端上的输入和输出,并与交互式程序进行交互。

expect_continue 在上方表示在匹配到yes或no时,继续等待下一个匹配,而不是退出循环

批量修改服务器用户密码

[root@wenzi wenzi]# cat oldPass.txt
192.168.28.156 root admin 22

[root@wenzi wenzi]# vim test.sh
#!/bin/bash

oldPassFile=/root/wenzi/oldPass.txt
newPassFile=/root/wenzi/newPass.txt

for i in `awk '{print $1}' $oldPassFile`;do
        user=`awk -v ip=$i 'ip==$1{print $2}' $oldPassFile`
        oldPwd=`awk -v ip=$i 'ip==$1{print $3}' $oldPassFile`
        port=`awk -v ip=$i 'ip==$1{print $4}' $oldPassFile`
        newPass=`cat /dev/urandom | tr -d -c "[:alnum:]" | head -c 12`
        echo $i $user $newPass $port >> $newPassFile
        expect << EOF
                spawn ssh -p $port $user@$i
                set timeout 10
                expect {
                        "(yes/no" {send "yes\r";exp_continue}
                        "password:" {send "$oldPwd\r";exp_continue}
                        "$user@" {send "echo $newPass | passwd --stdin $user;exit\r"}
        }
                expect eof
EOF
done

数据库备份

#!/bin/bash

dateTime=`date +'%Y%m%d%H%M%S'`
host=192.168.28.158
user=root
password=Admin.123
database=cs
bakDir=/data/backup

mysqldump -u$user -p${password} --single-transaction -R --triggers -B $database > $bakDir/$dateTime-all.sql

if [ $? -eq 0 ];then
        echo "backup success"
else
        echo "backup failure"
fi

#自动删除30天前的备份
find $bakDir -name "*all.sql" -mtime +30 -exec rm -f  {} \;

检查mysql主从结构中从数据库的状态

  • 本机的数据库服务是否正在运行
  • 能否与主数据库服务器正常通信
  • 能否使用授权用户连接数据库服务器
  • 本机的slave_IO进程是否处于YES状态
  • 本机的slave_SQL进程是否处于YES状态
#!/bin/bash

#检测mysql服务是否运行
lines=`pgrep mysqld | wc -l`
if [ $lines -gt 0 ];then
        echo "mysqld is running!"
else
        systemctl start mysqld
fi

#检测与主数据库能否通信
ping -c 3 192.168.28.158 &> /dev/null
if [ $? -eq 0 ];then
        echo "ping is sueccess!"
else
        echo "ping is failure!"
fi

#检测用户能否连接数据库服务器
host=192.168.28.158
user=rep
password='Admin.123'
mysql -h $host -u$user -p$password -e 'quit' &> /dev/null
if [ $? -eq 0 ];then
        echo "connect is sueccess!"
else
        echo "connect is failure!"
fi

#检测本机IO线程和SQL线程
IO=`mysql -uroot -p'Admin.123' -e "show slave status\G" 2> /dev/null | grep 'Slave_IO_Running:' | awk '{print $2}'`
SQL=`mysql -uroot -p'Admin.123' -e "show slave status\G" 2> /dev/null  | grep 'Slave_SQL_Running:' | awk '{print $2}'`
if [ $IO == 'Yes' ] && [ $SQL == 'Yes' ];then
        echo "IO and SQL connect success"
else
        echo "IO and SQL connect failure"

说明:

mysql -uroot -p'Admin.123' -e "show slave status\G" 2> /dev/null 中2> /dev/null是为了排除mysql明文登录时的Warning信息

PV过量实现防火墙自动封禁IP

仅供参考,未经过实测,AI修正后的脚本

#!/bin/bash

log=/tmp/tmp.log

[ -f $log ] || touch $log

function add_iptales {
    while read line
    do
        ip=$(echo $line | awk '{print $2}')
        count=$(echo $line | awk '{print $1}')
        if [ $count -gt 100 ] && [ $(iptables -L -n | grep "$ip" | wc -l) -lt 1 ]
        then
            iptables -I INPUT -s $ip -j DROP
            echo -e "$ip is dropped" >> /tmp/droplist.log
        fi
    done < $log
}

function main {
    while true
    do
        netstat -an | grep "EST" | awk -F '[:]+' '{print $6}' | sort | uniq -c >> $log
        add_iptales
        sleep 180
    done
}

main

说明:

PV(Page View)是指页面浏览量,通常是衡量网站或网页流量和活跃度的主要指标。在网络安全领域,PV过量通常指的是某个IP地址对特定网站或服务产生了过高的页面浏览量,这可能会引起防火墙的封锁。

检测服务器网卡流量

#!/bin/bash

#收集网卡名称,本地回环口lo除外
interfaces=`ifconfig | awk -F ':' '/flags/ {print$1}' | grep -v 'lo'`

for i in $interfaces;do
        ip=`ifconfig ens160 | awk 'NR==2 {print $2}'`
        rxBytes=`ifconfig ens160 | grep "RX packets" | awk '{print $6 $7}' | tr -d '()'`
        txBytes=`ifconfig ens160 | grep "TX packets" | awk '{print $6 $7}' | tr -d '()'`
        echo -e "网卡:$i\nIP:$ip\n下行流量:$rxBytes\n上行流量:$txBytes"
done

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值