Shell 脚本常用命令
- 一.日志打印
- 1.信息打印效果
- 2.占位符打印效果
- 二.文件检索
- 1.文件夹查找
- 2.文件名称
- 3.文件内容检索
- 三.字符串处理
- 1.字符串截取
- 2.字符串长度获取
- 3.字符串判断
- 4.数字判断
- 5.数字运算
- 四.日期获取
- 五.文件遍历
- 1.遍历获取修改时间和MD5
- 2.Find 查找
- 六.循环重试
- 1.While 循环
- 2.For 循环
- 七.数组定义和打印
- 1.定义并打印
- 2.遍历数组
- 八.IPV4 IP 地址校验
- 1.正则匹配校验
- 2.IP 封禁
一.日志打印
#!/bin/bash
SERVER_RUN=running
SERVER_STO=stopped
## 获取时间
get_current_time(){
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
}
## 文字 30:黑 31:红 32:绿 33:黄 34:蓝 35:紫 36:深绿 37:白
## 背景 40:黑 41:红 42:绿 43:黄 44:蓝 45:紫 46:深绿 47:白
## \033[0m 关闭所有属性
## \033[1m 高亮
## \033[2m 半高亮
## \033[3m 斜体 (不生效)
## \033[4m 下划线
## \033[5m 闪烁 (即文字闪烁)
## \033[7m 反显 (即背景色和文字颜色相反)
## \033[8m 消隐
## \033[30m -- \33[37m 设置前景色
## \033[40m -- \33[47m 设置背景色
## \033[nA 光标上移n行
## \033[nB 光标下移n行
## \033[nC 光标右移n行
## \033[nD 光标左移n行
## \033[y;xH设置光标位置
## \033[2J 清屏
## \033[K 清除从光标到行尾的内容
## \033[s 保存光标位置
## \033[u 恢复光标位置
## \033[?25l 隐藏光标
## \033[?25h 显示光标
## printf "%-10s %5d\n" "apple" 3 ==> apple 10 个字符左对齐 3 5个字符右对齐
## printf '%s\n' hhaha
## 文字颜色
F_BLACK='\033[30m'
F_RED='\033[31m'
F_GREEN='\033[32m'
F_YELLOW='\033[33m'
F_BLUE='\033[34m'
F_PURPLE='\033[35m'
F_DEEP_GREEN='\033[36m'
F_WHITE='\033[37m'
## 背景颜色
B_BLACK='\033[40m'
B_RED='\033[41m'
B_GREEN='\033[42m'
B_YELLOW='\033[43m'
B_BLUE='\033[44m'
B_PURPLE='\033[45m'
B_DEEP_GREEN='\033[46m'
B_WHITE='\033[47m'
## 样式
HIG_LIGHT='\033[1m'
BLINK='\033[5m'
STYLE_CLEAR='\033[0m'
###################################
## 打印内容
###################################
print_format(){
## 高亮
IS_HIGLIGHT=$1
if [[ "${IS_HIGLIGHT}" == "0" ]]; then
IS_HIGLIGHT=''
else
IS_HIGLIGHT='\033[1m'
fi
## 下划线
IS_UNDER_LINE=$2
if [[ "${IS_UNDER_LINE}" == "0" ]]; then
IS_UNDER_LINE=''
else
IS_UNDER_LINE='\033[4m'
fi
## 闪烁
IS_BLINK=$3
if [[ "${IS_BLINK}" == "0" ]]; then
IS_BLINK=''
else
IS_BLINK='\033[5m'
fi
## 是否换行
IS_WRAP=$4
if [[ "${IS_WRAP}" == "0" ]]; then
IS_WRAP=''
else
IS_WRAP='\n'
fi
## 文字和背景色
FONT_COLOR=$5
BACKGROUND_COLOR=$6
INFO=$7
## 打印
printf "${IS_HIGLIGHT}${IS_UNDER_LINE}${IS_BLINK}\033[${FONT_COLOR}m\033[${BACKGROUND_COLOR}m${INFO}${STYLE_CLEAR}${IS_WRAP}"
}
print_format 0 0 0 1 31 40 "Hello World"
print_format 0 0 1 1 31 40 "Hello World"
print_format 0 1 1 1 31 40 "Hello World"
print_format 1 1 1 1 31 40 "Hello World"
###################################
## 打印内容 服务状态
###################################
print_status(){
server=$1
status=$2
if [[ "${status}" == "${SERVER_RUN}" ]]; then
style=${F_GREEN}
else
style=${BLINK}${F_RED}
fi
printf "%-20s ${HIG_LIGHT}${style}%s${STYLE_CLEAR}\n" ${server} ${status}
}
###################################
## 打印服务状态
###################################
print_server(){
get_current_time
echo -e "[$CURRENT_TIME] ${F_YELLOW}Start to print server status${STYLE_CLEAR}"
print_status spring-boot ${SERVER_RUN}
print_status spring-clould ${SERVER_STO}
print_status nginx ${SERVER_STO}
print_status hadoop ${SERVER_STO}
print_status kafka ${SERVER_RUN}
print_status xxl-job ${SERVER_RUN}
}
print_server
1.信息打印效果
图片无法展示闪烁效果
2.占位符打印效果
二.文件检索
## 检索命令: find
## 可用参数
-mount, -xdev : 只检查和指定目录在同一个文件系统下的文件,避免列出其它文件系统中的文件
-amin n : 在过去 n 分钟内被读取过
-anewer file : 比文件 file 更晚被读取过的文件
-atime n : 在过去n天内被读取过的文件
-cmin n : 在过去 n 分钟内被修改过
-cnewer file :比文件 file 更新的文件
-ctime n : 在过去n天内被修改过的文件
-empty : 空的文件
-name name, -iname name : 文件名称符合 name 的文件。iname 会忽略大小写
-size n : 文件大小 是 n 单位,b 代表 512 位元组的区块,c 表示字元数,k 表示 kilo bytes,w 是二个位元组。
-type d : d-目录;c-字型装置文件;b-区块装置文件;p-具名贮列;f-一般文件;l-符号连结;s-socket
-pid n : pid 是 n 的文件
1.文件夹查找
find ./ -type d
2.文件名称
## 具体文件名
find ./ -type f -name kafka.log
## 模糊文件名
find ./ -type f -name kafka*
3.文件内容检索
## 检索文件
find test/ -type f | xargs grep 123
## 模糊文件检索
find test/ -type f -name spring* | xargs grep 123
find test/ -type f -name *.log | xargs grep 123
三.字符串处理
1.字符串截取
项目 | Value |
---|---|
${val:start:length} | 左侧从 0 开始计算,从 start 开始向右截 length 长 |
${val:start} | 左侧从 0 开始计算,从 start 开始向右截到末尾 |
${val:0-start:length} | 右侧从 1 开始计算,从 start 开始向右截 length 长 |
${val:0-start} | 右侧从 1 开始计算,从 start 开始向右截到末尾 |
${val#*chars} | * 模糊匹配,截取从左向右第一次出现 chars 的位置右侧。不包含 chars |
${val##*chars} | * 模糊匹配,截取从左向右最后一次出现 chars 的位置右侧。不包含 chars |
${val%chars*} | * 模糊匹配,截取从右向左第一次出现 chars 的位置左侧。不包含 chars |
${val%%chars*} | * 模糊匹配,截取从右向左最后一次出现 chars 的位置左侧。不包含 chars |
#!/bin/bash
## 字符串截取 ${val:a:b} 从左侧 0 开始,第 a 位开始截取 b 位,b 缺省时截取到末尾
echo "从左开始截..."
val=123456789
echo ${val:2:3}
echo ${val:2}
echo "" && echo "从右开始截..."
## 字符串截取 ${val:0-a:b} 从右侧 1 开始,第 a 位开始截取 b 位,b 缺省时截取到末尾(都是从左向右截)
val=123456789
echo ${val:0-2:1}
echo ${val:0-2}
echo "" && echo " # 匹配并截取右侧字符串..."
## 截取右侧字符 # 向右截 *str 其中 * 表示模糊匹配,
val=12333456789
echo "从第一个 3 开始截取右侧的 " ${val#*3}
echo "从第一个 23 开始截取右侧的" ${val#*23}
echo "从最后一个 3 开始截取右侧的 " ${val##*3}
echo "从最后一个 23 开始截取右侧的" ${val##*23}
echo "不带模糊匹配则要写完整 " ${val#123}
echo "" && echo " % 匹配并截取左侧字符串..."
## 截取右侧字符 # 向右截 *str 其中 * 表示模糊匹配,
val=12333456789
echo "从第一个 3 开始截取左侧的 " ${val%3*}
echo "从第一个 23 开始截取左侧的" ${val%23*}
echo "从最后一个 3 开始截取左侧的 " ${val%%3*}
echo "从最后一个 23 开始截取左侧的" ${val%%23*}
echo "不带模糊匹配则要写完整 " ${val%6789}
效果演示
2.字符串长度获取
#!/bin/bash
## 字符串长度
val="1234 56"
echo "直接统计 " ${#val}
echo "AWK分割后数组长度 " `echo ${val} | awk '{print length($0)}'`
echo "AWK分割后域个数 " `echo ${val} | awk -F "" '{print NF}'`
echo "wc -c 统计字符(默认带换行符) " `echo ${val} | wc -c`
echo "wc -c 统计字符(去掉换行符) " `echo -n ${val} | wc -c`
echo "expr 的 length 方法 " `expr length "${val}"`
3.字符串判断
#!/bin/bash
param=abcde
val=123456
var=
## 字符串为空
echo ------------------------------------
if [[ -z $var ]]; then
echo "var is empty"
else
echo "var is not empty"
fi
## 字符串非空
echo ------------------------------------
if [[ -n $val ]]; then
echo "val is not empty"
else
echo "val is empty"
fi
## 取反
if [[ ! -n $val ]]; then
echo "val is empty"
else
echo "val is not empty"
fi
## 字符串相等
echo ------------------------------------
if [[ $param == abcde ]]; then
echo "param = abcde"
else
echo "param != abcde"
fi
## 带引号
if [[ "$val" == "1234568" ]]; then
echo "val = 123456"
else
echo "val != 1234568"
fi
## 字符串不相等
echo ------------------------------------
if [[ $param != abcdef ]]; then
echo "param != abcdef"
else
echo "param = abcde"
fi
4.数字判断
#!/bin/bash
val=123
## > 12
if (($val > 21)); then
echo "val > 21"
else
echo "val < 21"
fi
## < 321
if (($val > 321)); then
echo "val > 321"
else
echo "val < 321"
fi
## -gt 21
if [ $val -gt 21 ]; then
echo "val -gt 21"
else
echo "val -lt 21"
fi
## -lt 321
if [ $val -gt 321 ]; then
echo "val -gt 321"
else
echo "val -lt 321"
fi
## >= 123
if (($val >= 123)); then
echo "val >= 123"
else
echo "val < 123"
fi
## -ge 123
if [ $val -ge 123 ]; then
echo "val -ge 123"
else
echo "val -lt 123"
fi
## < 321
if (($val < 321)); then
echo "val < 321"
else
echo "val >= 321"
fi
## -lt 321
if [ $val -lt 321 ]; then
echo "val < 321"
else
echo "val >= 321"
fi
## != 1
if (( $val != 1 )); then
echo "val != 1"
else
echo "val == 1"
fi
## != 1
if [ $val -ne 1 ]; then
echo "val -ne 1"
else
echo "val == 1"
fi
5.数字运算
#!/bin/bash
echo '5+4 =' $((5+4))
echo '5-4 =' $((5-4))
echo '5*4 =' $((5*4))
echo '5/4 =' $((5/4))
四.日期获取
#!/bin/bash
## 当前时间
date
## 年
echo $(date +'%Y')
## 月
echo $(date +'%m')
## 日
echo $(date +'%d')
## 年-月-日
echo $(date +'%Y-%m-%d')
## 年-月-日 时:分:秒
echo $(date +'%Y-%m-%d %H:%M:%S')
## 昨天
echo $(date -d '-1 day' +'%Y-%m-%d')
## 明天
echo $(date -d '+1 day' +'%Y-%m-%d')
## 明天
echo $(date -d '+1 day' +'%Y-%m-%d')
## 获取 10MIN 前
echo $(date -d '-10 min' +'%Y-%m-%d %H:%M:%S')
## 获取 10SEC 前
echo $(date -d '-10 sec' +'%Y-%m-%d %H:%M:%S')
## 今日为周几 0-6 日-六
echo $(date +'%w')
## 某天是周几 20230806
echo $(date -d '20230806' +'%w')
## 获取时间戳
echo $(date +'%s')
## 时间戳转成日期
echo $(date -d @1692051748 +'%Y-%m-%d %H:%M:%S')
五.文件遍历
1.遍历获取修改时间和MD5
#!/bin/bash
LOG_FILE_PATH=/home/test
CURRENT_DAY_TIME=$(date +'%Y%m%d')000000
for file in `ls ${LOG_FILE_PATH}`; do
## 获取修改时间
unixTime=`stat -c '%Y' $LOG_FILE_PATH/$file`
## unixTime=`echo "$(date -d @$unixTime +'%Y-%m-%d %H:%M:%S') => $(date -d @$unixTime +'%Y%m%d%H%M%S')"`
unixTime=$(date -d @$unixTime +'%Y%m%d%H%M%S')
## 计算 MD5 并转大写
md5=`md5sum $LOG_FILE_PATH/$file | awk '{ print $1 }' | tr [a-z] [A-Z]`
## 打印文件名 修改时间
printf '%-32s %s\n' $file "$unixTime $md5"
## 获取今天修改的
if [ $unixTime -ge $CURRENT_DAY_TIME ]; then
echo $file
fi
done
2.Find 查找
## 获取近1天
find /home/test/ -type f -mtime -1
## 获取近3天
find /home/test/ -type f -mtime -3
六.循环重试
1.While 循环
#!/bin/bash
func(){
RETRY_TIMES=3
## 循环重试
while [[ 1 == 1 ]]; do
echo 'pls input one char'
read input
##
if [[ $input != "exit()" ]]; then
echo "you input " $input
fi
##
RETRY_TIMES=$(($RETRY_TIMES-1))
##
if [[ $input == "exit()" ]]; then
return 0
fi
##
if [ $RETRY_TIMES -le 0 ]; then
return 1
fi
done
}
## 调用方法
func
## 退出循环
echo result $?
2.For 循环
#!/bin/bash
for (( i = 0; i < 10; i++ )); do
echo $i
done
七.数组定义和打印
1.定义并打印
#!/bin/bash
arr=(1 2 3 4 5 6 7 8 9)
echo ${arr[@]}
echo ${arr[*]}
list="a b c d e f"
arr=($list)
echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}
arrs[0]=hello
arrs[1]=world
arrs[3]=how
echo ${arrs[@]}
array=([0]=a [1]=b [2]=c)
echo ${array[@]}
2.遍历数组
#!/bin/bash
list="a b c d e f"
arr=($list)
for i in ${arr[@]}; do
echo $i
done
八.IPV4 IP 地址校验
1.正则匹配校验
#!/bin/bash
## ipv4 点分十进制
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 ok."
else
echo "$IP not ok!"
fi
else
echo "$IP Format error!"
fi
}
check_ip 192.168.1.2
check_ip 192.168.1.256
check_ip 192.168.1
2.IP 封禁
#!/bin/bash
## 应用端口
PORT=80
## 访问 IP 日志
logfile=/var/log/access.log
## 单位为 MIN 示例为近 5MIN
ACCESS_LIMIT=3
ACCESS_SCOPE=5
ACCESS_TMP=''
## 获取时间范围
d1=`date -d "-$ACCESS_SCOPE min" +"%Y%m%d%H%M"`
ipt=/sbin/iptables
ipa=/tmp/ip_analysis.log
ipb=/tmp/ip_block.log
## 封禁
block()
{
## 计算时间
ACCESS_TMP=$d1'*'
for (( i = 1; i < $ACCESS_SCOPE; i++ )); do
ACCESS_TMP=${ACCESS_TMP}'\|'$(($d1-$i))'*'
done
## 或匹配
grep ${ACCESS_TMP} $logfile|awk '{print $1}'|sort -n|uniq -c|sort -n > $ipa
##
cat $ipa
## 利用for循环将次数超过 ACCESS_LIMIT 的IP依次遍历出来并予以封禁
[[ -f $ipb ]] && rm -rf $ipb
for i in `awk '$1>3 {print $2}' $ipa`
do
$ipt -I INPUT -p tcp --dport $PORT -s $i -j REJECT
echo "`date +%F-%T` $i" >> $ipb
done
## 打印禁用的 ip
[[ -f $ipb ]] && cat $ipb
}
## 解封
unblock()
{
## 将封禁后所产生的 pkts 数量小于 10 的 IP 解封
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
}
case $1 in
"block")
block
;;
"unblock")
unblock
;;
*)
echo 'pls input block|unblock'
;;
esac
## 查看 iptables
/sbin/iptables -nvL INPUT --line-numbers