当前位置: 首页 > news >正文

分享一个shell脚本

分享一个五年前项目上写的shell脚本,隐去了一些关键信息,用AI给加上了注释,可以给初学shell脚本的程序员一些启发。
脚本的功能是对一个数据库实例下的所有数据库(同结构的数据库)执行相同的升级脚本,支持选项解析、断点执行、错误记录,以及报错跳过继续执行。有完整的提示功能。
你可以保存为test.sh,然后输入以下命令查看提示

./test.sh -h
./test.sh -s=xxxx.sql -b=0

以下是完整的shell脚本,AI添加的注释,有些地方可能不准确,不懂的地方可以搜一下,也有助于加深理解。脚本浅陋,有错误的地方欢迎指摘。(抱拳ing…)

#!/bin/bash# 设置删除字符为Ctrl+h
stty erase ^h# 打印DBTools的标题信息
echo -e "
+------------------------------------------------------+
|                       DBTools                        |
+------------------------------------------------------+
"#  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> shell 配置选项校验   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# 使用getopt工具解析命令行参数,支持短选项(-v, -h, -s, -b)和长选项(--version, --help, --script, --breakpoint)
# -o 指定短选项
# --long 指定长选项
# -n 指定错误信息的前缀
# -- 表示参数解析结束
ARGS=`getopt -o vhs:b: --long help,version,script:,breakpoint: -n "An error occurred while parsing the parameter !" -- "$@" 2>error.txt`# 输出解析后的参数(调试用,当前被注释掉)
# echo ">>>>>>>>>>>>>>>>:${ARGS}"# 检查解析过程中是否有错误信息
if [[ `cat error.txt|wc -w` != 0  ]];
then# 若有错误信息,提示用户可以使用 -h 或 --help 查看帮助文档echo "Command line options resolve exceptions, you can type [-h | --help] to view the help documentation!"# 逐行输出错误信息while read linedoecho -e "\t "$linedone < error.txt# 删除错误信息文件rm -f error.txt# 退出脚本,返回状态码1表示异常退出exit 1
fi# 用于存储需要执行的SQL脚本文件名
needSql=""
# 断点索引,用于指定从哪个数据库实例开始执行升级操作
breakpoint=0# 配置项校验及参数设置
# 使用eval将解析后的参数重新设置到位置参数中
eval set -- "$ARGS"
# 循环处理每个参数
while true;docase "$1" in-s|--script)# 输出当前配置的升级增量脚本文件信息needSql=$2echo "Configured upgrade incremental script file:${needSql}"# 判断是否为配置项赋值if [  ${#needSql} == 0  ];then# 若未赋值,提示用户输入有效的SQL脚本文件echo "Please enter a value for option -s|--script,the value must be an accessible SQL script file"# 退出脚本,返回状态码1表示异常退出exit 1fi# 移动到下两个参数shift 2;;-b|--breakpoint)# 判断输入的breakpoint是否为>=0的整数,否则为非法数值echo $2 |grep [^0-9] > /dev/nullif [ $2 -lt 0  ]then# 若输入值小于0,提示用户输入有效的断点值echo "Please enter a value for option -b|--breakpoint,the value must be an integer greater than or equal to 0."# 退出脚本,返回状态码1表示异常退出exit 1else# 若输入值合法,将其赋值给breakpoint变量breakpoint=$2fi# 移动到下两个参数shift 2;;-v|--version)# 输出DBTools的版本信息echo -e "Name: DBTools\nDescription: Batch upgrade for multiple database instances\nDate: 2020-06-02 17:22:10\nAuthor: Song.Yang"# 移动到下一个参数shift# 退出脚本,返回状态码0表示正常退出exit 0;;-h|--help)# 输出帮助信息,包括脚本的使用方法和各选项的说明echo -e ">>>: sh DBTools.sh --script=upgrade.sql [--breakpoint=10]
Usage: DBTools.sh [OPTIONS]-h, --help     Display this help and exit.-v, --version  Display this tool's version information-s, --script   Required option. Used to specify the upgrade SQL script.eg:-s=upgrade.sql / --script=upgrade.sql-b, --breakpointOptional. This is an integer greater than or equal to 0.When not configured, all database instances will be upgraded.After configuration, the database will be upgraded from the databasewith index n. The value cannot be greater than the sum of all databases,the shell program will verify.eg:-b=5 / --breakpoint=10  "echo ""# 移动到下一个参数shift# 退出脚本,返回状态码0表示正常退出exit 0;;--)# 表示参数解析结束,跳出循环shiftbreak;;*)# 若遇到未知选项,输出错误信息并退出脚本echo "Unknown Option:{$1}"exit 1;;
esac
done# 再次校验两个重要参数[script breakpoint]的配置值
if [  ${#needSql} == 0  ];
then# 若needSql为空,提示用户输入有效的SQL脚本文件echo "Please enter a value for option -s|--script,the value must be an accessible SQL script file"# 退出脚本,返回状态码1表示异常退出exit 1
fi# 若breakpoint为空,将其赋值为0
if [  ${#breakpoint} == 0  ];
thenbreakpoint=0
fi
# 输出调试信息(当前被注释掉)
# echo "${needSql}---${breakpoint}"#  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
# 输出注意事项,提醒用户在执行DDL语句时的注意事项
echo -e "
Attention:Since DDL statements can not roll back in the event of an error, please make sure that the following points are executed to avoid inconsistent scheme structures:1,The structure is consistent across multiple target databases to be incrementally updated;2,The current incremental script should not report an exception when executing against the target database
"# 提示用户确认注意事项,按任意键继续,按Ctrl+C退出
read -p "If you confirm the attention, press any key to continue, or press (CTRL + C) to exit" -n 1 blockPoint1
echo ""# 【1】检查增量脚本
echo "【1】,Check the incremental script............"# 再次检查needSql是否为空
if [  ${#needSql} == 0  ];
then# 若为空,提示用户输入有效的SQL脚本文件echo "Please enter a value for option -s|--script,the value must be an accessible SQL script file"# 退出脚本,返回状态码1表示异常退出exit 1
fi# 判断当前的脚本是否存在且为普通文件
if [[ -e $needSql  &&  -f $needSql ]]
then# 若存在,输出检查通过信息echo "check passed........"
else# 若不存在,提示用户输入正确的SQL脚本文件echo "Please enter a correct value for option -s|--script,the value must be an accessible and existing SQL script file!"# 退出脚本,返回状态码1表示异常退出exit 1
fi# 提示用户确认要执行的增量脚本
read   -p "Verify that the incremental script you will execute is: ${needSql}?(y/n)" -n 1 confirmSql
# 输出确认字符(调试用,当前被注释掉)
# echo "confirmSql:>>>>>>   ${confirmSql} "# 根据用户的确认字符进行处理
if [[ -z $confirmSql  ||  $confirmSql == "y"  ]]
thenecho -e " \n "# 若用户输入为空或y,继续执行脚本# 退出当前shell脚本(当前被注释掉)# exit 1
elif [ $confirmSql == "n" ]
then# 若用户输入n,退出脚本echo ""exit 1
else# 若用户输入非法字符,输出错误信息并退出脚本echo -e " \n Illegal confirmation character,You will exit the current shell program."exit 1
fi# 【2】输入数据库连接信息并验证
echo "【2】,Enter the database connection information and validate............"
# 提示用户输入数据库的IP或主机名
read  -p "Please enter the correct IP or host name:" ip
# 提示用户输入数据库的端口号
read  -p "Please enter the correct port number:" port
# 提示用户输入数据库的登录用户名
read  -p "Please enter the correct login username:" usname
# 提示用户输入数据库的密码
read  -p "Please enter the correct password:" password# 可以手动配置IP和其他连接信息,注释掉上面的手动输入部分
:<<EOF
ip='xxxxxxxx'
port='3306'
usname='root'
password='123456'
EOF# 输出用户输入的连接信息并提示正在验证
echo -e "The connection information you entered is:IP: ${ip},Port: ${port},usname: ${usname},pswd: ${password}  \nVerifying the connection information........."# 尝试连接数据库并执行select now()语句,将结果存储在conresult变量中
conresult=`mysql -h${ip} -P${port} -u${usname} -p${password} -e "select now()" 2>&1`
# 输出连接结果(调试用,当前被注释掉)
# echo "${conresult}"# 将连接结果转换为小写
lowercaseConresult=`echo ${conresult}| tr '[A-Z]' '[a-z]'`# 判断连接结果中是否包含error关键字
if [[ $lowercaseConresult =~ "error"  ]];
then# 若包含error,输出错误信息并退出脚本echo "An error occurred while verifying connection information!the error message:"echo "${conresult}"exit 1
else# 若不包含error,输出连接信息验证通过信息echo -e "The connection information is validated。。。。。。。。。\n\n"
fi# 【3】获取符合条件的目标数据库实例
echo -e "【3】,Gets the eligible target database instance............"
echo "Gets all database names starting with[ db ]......."
# 连接数据库并获取所有以db开头的数据库名称,将错误输出重定向到/dev/null以避免干扰
result=`mysql -h${ip} -P${port} -u${usname} -p${password}  -e "show databases" 2>/dev/null | grep '\<db'  `
# 输出查询结果(调试用,当前被注释掉)
# echo ${result}echo "---------------------------------------------------------"
# 将查询结果分割为数组
#1. ${result// / }:参数扩展
#这是 Bash shell 的参数扩展特性,具体格式为 ${parameter/pattern/string},其作用是对变量 parameter 里匹配 #pattern 的部分进行替换,替换内容为 string。
#result:这是变量名,代表要处理的字符串。
#//:是替换操作符,// 表示全局替换,也就是把字符串里所有匹配 pattern 的部分都替换掉。
#第一个空格 :是要匹配的模式,在这里代表空格字符。
#第二个空格 :是要替换成的字符串,这里同样是空格。由于两个空格相同,所以本质上没有进行实际的替换,只是借助这个操作来分割字符串。
#2. ( ... ):数组赋值
#在 Bash 里,( ... ) 用来定义数组。通过把 ${result// / } 的结果放在 ( ... ) 中,就能把分割后的字符串元素赋值给数组 dbarray。
dbarray=(${result// / })
# 获取数组的长度
dbArrCount=${#dbarray[@]}
# 输出符合条件的数据库实例数量
echo -e "There are ${dbArrCount} db instances that meet the criteria \n\n"
# 若数组长度为0,说明没有符合条件的数据库实例,输出错误信息并退出脚本
if [ ${dbArrCount} -eq 0  ]
thenecho -e "\nThere is no qualified database instance in the current database, please confirm whether the connection information is correct!!\n"exit 1
fi# 【4】开始处理数据库实例
echo  "【4】,Start processing the database instance............"
# 创建结果文件,用于存储标准输出的信息,文件名包含当前日期和时间
resultfile="result_"$( date "+%Y-%m-%d_%H-%M-%S"  )".txt"
# 创建结果文件
touch ${resultfile}
# 输出结果文件的信息
echo -e ">>>>>The result of this incremental execution will be output to file:${resultfile}\n"# 根据breakpoint判断当前是否为中断继续执行
# 1. 大于0小于数组长度的为增量执行
# 2. 大于等于数组长度的为错误断点
if [[ $breakpoint -gt 0 && $breakpoint -lt $dbArrCount   ]]
then# 若为增量执行,输出提示信息echo "Notice: You have selected breakpoint mode to continue execution. "echo "		The breakpoint you have inputed is:[ $breakpoint ]"
elif [[ $breakpoint -ge $dbArrCount  ]]
then# 若断点设置大于等于总目标数据库实例数量,输出错误信息并退出脚本echo -e "Total number of the target database instances:[ $dbArrCount ]\nThe breakpoint you entered:[ $breakpoint ]\nThe breakpoint setting should be less than the total number of target database instances!\nThe program terminates!!!"exit 1
elseecho ""
fi# 从断点处开始处理数据库实例
i=$breakpoint
for((;i<${dbArrCount};i++))
do# 清空错误信息文件,用于记录从错误输出中输出的信息,注意,warning也是错误输出,但不是错误echo "" > error.txt# 屏幕输出当前处理的数据库实例信息echo " 【"$(expr ${i} + 1 )"/${dbArrCount}】: ${dbarray[${i}]} start Processing........"# 将当前处理的数据库实例信息记录到结果文件中echo ">>>>>>>>>>>>>>>>>>>>>>>>DB Name: ${dbarray[${i}]} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> ${resultfile}# 执行SQL脚本并将结果存储在handleresult变量中,同时将错误输出重定向到error.txt文件中handresult=`mysql -h${ip} -P${port} -u${usname} -p${password}  --line-numbers -t  -s ${dbarray[${i}]}   <${needSql}  2>error.txt`echo -e "\tthe process deal......"# 将执行结果输入到result.txt文件中echo -e "${handresult}" >> ${resultfile}# 检查错误信息文件中是否有内容if [[ `cat error.txt|wc -w` != 0  ]];then# 将错误输出信息转换为小写lowercaseErrorHandleresult=`cat error.txt| tr '[A-Z]' '[a-z]'`# 判断错误信息中是否包含error关键字if [[ $lowercaseErrorHandleresult =~ "error"  ]];then# 若包含error,将错误信息输入到结果文件中cat error.txt >> ${resultfile}# 在结果文件中添加当前数据库处理结束符echo -e "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" >> ${resultfile}# 输出错误信息echo -e "\tDB Name: ${dbarray[${i}]} occurred an error , the error message is :"# 逐行输出错误信息while read linedoecho -e "\t "$linedone < error.txt# 若当前出错的数据库为最后一个数据库实例,则不必确认继续执行或者中断执行,直接跳出循环if [ ` expr ${i} + 1  ` -eq $dbArrCount  ];thenbreakfi# 提示用户注意异常SQL的错误行号并手动处理,输入y或回车继续执行下一个数据库实例,输入其他字符结束当前进程echo -e "\tNotice the error line number of the exception SQL and handle it manually,Enter [y/ Enter] to continue execution of the next database instance,Or enter any other character to end the current process"fifi
done

相关文章:

  • 大模型在胃十二指肠溃疡预测及治疗方案制定中的应用研究
  • L1-103 整数的持续性
  • 【TI MSPM0】ADC进阶学习
  • 家政小程序预约系统框架设计
  • 计算斐波那契数列
  • 天梯赛L1-22-25
  • SpringBoot 与 Vue3 实现前后端互联全解析
  • 日常记录-CentOS 9安装java17
  • GitLab-获取token(访问令牌)
  • 用css给div列表加个序号
  • uniapp的h5,打开的时候,标题会一闪而过应用名称,再显示当前页面的标题
  • uniapp 自定义tabbar
  • D1084低功耗LDO稳压器:技术解析与应用设计
  • 各证券公司QMT的本地VSCode开发环境配置指南
  • CRUD3
  • Bad Request 400
  • 什么是 矩阵号 ?为什么要做海外矩阵?
  • Axure高保真AI算法训练平台
  • SQL2API 核心理念:如何重构数据服务交付范式
  • github配置ssh,全程CV
  • 2025年度沪惠保参保今开启:保费不变,国内特药种类扩增
  • 宁波一季度GDP为4420.5亿元,同比增长5.6%
  • 印度空军计划增购40架法制“阵风”战机,此前已购买36架
  • 女子伸腿阻止列车关门等待同行人员,被深圳铁路警方行政拘留
  • 对话地铁读书人|来自大学教授的科普:读书日也是版权日
  • 女外交官杨扬出任中国驻圭亚那大使