最近练习的一些经典Shell脚本实战30个
Posted 抛物线.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最近练习的一些经典Shell脚本实战30个相关的知识,希望对你有一定的参考价值。
首先,对于运维行业,不管是云计算运维还是linux运维都不开shell的使用,那么最近收集实战了一些很有用的shell脚本实例,这里分享给大家。
目录:
1、获取随机字符串或数字
2、定义一个颜色输出字符串函数
3、批量创建用户
4、检查软件包是否安装
5、检查服务状态
6、检查主机存活状态
7、监控CPU、内存和硬盘利用率
8、批量主机磁盘利用率监控
9、检查网站可用性
10、检查mysql主从同步状态
11、iptables自动屏蔽访问网站频繁的IP
12、判断用户输入的是否为IP地址
13、判断用户输入的是否为数字
14、给定目录找出包含关键字的文件
15、监控目录,将新创建的文件名追加到日志中
16、给用户提供多个网卡选择
17、查看网卡实时流量
18、MySQL数据库备份
19、nginx服务管理脚本
20、用户根据菜单选择要连接的Linux主机
21、从FTP服务器下载文件
22、连续输入5个100以内的数字,统计和、最小和最大
23、将结果分别赋值给变量
24、批量修改文件名
25、统计当前目录中以.html结尾的文件总大
26、扫描主机端口状态
27、Expect实现SSH免交互执行命令
28、批量修改服务器用户密码
29、打印乘法口诀
30、getopts工具完善脚本命令行参数
开头加解释器:#!/bin/bash
语法缩进,使用四个空格;多加注释说明。
命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。
默认变量是全局的,在函数中变量local指定为局部变量,避免污染其他作用域。
有两个命令能帮助我调试脚本:set -e 遇到执行非0时退出脚本,set-x 打印执行过程。
写脚本一定先测试再到生产上。
1.获取随机字符串或数字
方法1:
# echo $RANDOM |md5sum |cut -c 1-8
471b94f2
方法2:
# openssl rand -base64 4
vg3BEg==
方法3:
# cat /proc/sys/kernel/random/uuid |cut -c 1-8
ed9e032c
- 获取随机8位数字
方法1:
# echo $RANDOM |cksum |cut -c 1-8
23648321
方法2:
# openssl rand -base64 4 |cksum |cut -c 1-8 #cksum:打印CRC效验和统计字节
38571131
方法3:
# date +%N |cut -c 1-8
69024815
- 定义一个颜色输出字符串函数
方法1:
function echo_color()
if [ $1 == "green" ]; then
echo -e "\\033[32;40m$2\\033[0m"
elif [ $1 == "red" ]; then
echo -e "\\033[31;40m$2\\033[0m"
fi
方法2:
function echo_color()
case $1 in
green)
echo -e "[32;40m$2[0m"
;;
red)
echo -e "[31;40m$2[0m"
;;
*)
echo "Example: echo_color red string"
esac
使用方法:echo_color green "test"
function关键字定义一个函数,可加或不加。
3、批量创建用户
#!/bin/bash
DATE=$(date +%F_%T)
USER_FILE=user.txt
echo_color()
if [ $1 == "green" ]; then
echo -e "[32;40m$2[0m"
elif [ $1 == "red" ]; then
echo -e "[31;40m$2[0m"
fi
# 如果用户文件存在并且大小大于0就备份
if [ -s $USER_FILE ]; then
mv $USER_FILE $USER_FILE-$DATE.bak
echo_color green "$USER_FILE exist, rename $USER_FILE-$DATE.bak"
fi
echo -e "User Password" >> $USER_FILE
echo "----------------" >> $USER_FILE
for USER in user1..10; do
if ! id $USER &>/dev/null; then
PASS=$(echo $RANDOM |md5sum |cut -c 1-8)
useradd $USER
echo $PASS |passwd --stdin $USER &>/dev/null
echo -e "$USER $PASS" >> $USER_FILE
echo "$USER User create successful."
else
echo_color red "$USER User already exists!"
fi
done
- 检查软件包是否安装
#!/bin/bash
if rpm -q sysstat &>/dev/null; then
echo "sysstat is already installed."
else
echo "sysstat is not installed!"
fi
6、检查主机存活状态
方法1:将错误IP放到数组里面判断是否ping失败三次
#!/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失败三次
#!/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失败
#!/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
7、监控CPU、内存和硬盘利用率
1)CPU
借助vmstat工具来分析CPU统计信息。
#!/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==3print $13 )
SY=$(vmstat |awk NR==3print $14 )
IDLE=$(vmstat |awk NR==3print $15 )
WAIT=$(vmstat |awk NR==3print $16 )
USE=$(($US+$SY))
if [ $USE -ge 50 ]; then
echo "
Date: $DATE
Host: $IP
Problem: CPU utilization $USE
" | mail -s "CPU Monitor" $MAIL
fi
2)内存
#!/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
3)硬盘
#!/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 [: ]+ BEGINOFS="="/^Disk /dev/printf "%s=%sG,",$2,$3 )
PART_USE=$(df -h |awk BEGINOFS="="/^/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
8、批量主机磁盘利用率监控
前提监控端和被监控端SSH免交互登录或者密钥登录。
写一个配置文件保存被监控主机SSH连接信息,文件内容格式:IP User Port
#!/bin/bash
HOST_INFO=host.info
for IP in $(awk /^[^#]/print $1 $HOST_INFO); do
USER=$(awk -v ip=$IP ip==$1print $2 $HOST_INFO)
PORT=$(awk -v ip=$IP ip==$1print $3 $HOST_INFO)
TMP_FILE=/tmp/disk.tmp
ssh -p $PORT $USER@$IP df -h > $TMP_FILE
USE_RATE_LIST=$(awk BEGINOFS="="/^/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
9、检查网站可用性
1)检查URL可用性
方法1:
check_url()
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%http_code" $1)
if [ $HTTP_CODE -ne 200 ]; then
echo "Warning: $1 Access failure!"
fi
方法2:
check_url()
if ! wget -T 10 --tries=1 --spider $1 >/dev/null 2>&1; then
#-T超时时间,--tries尝试1次,--spider爬虫模式
echo "Warning: $1 Access failure!"
fi
使用方法:check_url www.baidu.com
2)判断三次URL可用性
思路与上面检查主机存活状态一样。
方法1:利用循环技巧,如果成功就跳出当前循环,否则执行到最后一行
#!/bin/bash
check_url()
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%http_code" $1)
if [ $HTTP_CODE -eq 200 ]; then
continue
fi
URL_LIST="www.baidu.com www.agasgf.com"
for URL in $URL_LIST; do
check_url $URL
check_url $URL
check_url $URL
echo "Warning: $URL Access failure!"
done
方法2:错误次数保存到变量
#!/bin/bash
URL_LIST="www.baidu.com www.agasgf.com"
for URL in $URL_LIST; do
FAIL_COUNT=0
for ((i=1;i<=3;i++)); do
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%http_code" $URL)
if [ $HTTP_CODE -ne 200 ]; then
let FAIL_COUNT++
else
break
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
echo "Warning: $URL Access failure!"
fi
done
方法3:错误次数保存到数组
#!/bin/bash
URL_LIST="www.baidu.com www.agasgf.com"
for URL in $URL_LIST; do
NUM=1
while [ $NUM -le 3 ]; do
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "%http_code" $URL)
if [ $HTTP_CODE -ne 200 ]; then
FAIL_COUNT[$NUM]=$IP #创建数组,以$NUM下标,$IP元素
let NUM++
else
break
fi
done
if [ $#FAIL_COUNT[*] -eq 3 ]; then
echo "Warning: $URL Access failure!"
unset FAIL_COUNT[*] #清空数组
fi
done
10、检查MySQL主从同步状态
#!/bin/bash
USER=bak
PASSWD=123456
IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e show slave statusG |awk -F: /Slave_.*_Running/gsub(": ",":");print $0 ) #gsub去除冒号后面的空格
for i in $IO_SQL_STATUS; do
THREAD_STATUS_NAME=$i%:*
THREAD_STATUS=$i#*:
if [ "$THREAD_STATUS" != "Yes" ]; then
echo "Error: MySQL Master-Slave $THREAD_STATUS_NAME status is $THREAD_STATUS!"
fi
done
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 shell脚本上