作者:Chancel Yang, 创建:2019-08-30, 字数:6388, 已阅:730, 最后更新:2023-07-29
服务器上的备份脚本是好几年前写的,前段时间发现不工作了
最近也打算重新看一下Bash Shell脚本的语法,就趁着这个机会复习下
unix shell是一个命令行解释器或者说是shell,为类Unix操作系统提供一个命令行用户界面。这个shell既是一种交互式的命令语言,也是一种脚本语言,操作系统通过使用shell脚本来控制系统的执行
shell既是交互式命令语言又是脚本语言,操作系统使用它来控制使用shell脚本执行系统,用户通常使用终端仿真器与Unix shell进行交互;
通过串行硬件连接或Secure Shell直接操作对于服务器系统是常见的,所有Unix shell都提供文件名通配符、管道、这里的文档、命令替换、变量和控制结构、于条件测试和迭代
听起来很像python
,Shell目前主要有两大主流流派
大部分Linux发行版都是预设bash环境,bash是shell的一种
shell是一种统称符合其语法规则语言的简称
bash
的语法不复杂,对于有编程语言使用经验的人来说阅读一遍往往就记住了,网上的简中资料介绍太累赘了
因此,下面直接将一些语法点整理出来,以供参考
首先,bash
的脚本一般有开头标记来告诉环境需要什么脚本解释器,linux下script大部分情况下都是由bash解释器来执行的,一个输出Hello World
的脚本如下
编辑hello.sh
文件,内容如下
#!/bin/bash
echo "Hello World! "
赋予权限,并执行
chmod +x hello.sh
# 执行方法1. 使用指定解释器执行
/bin/bash hello.sh
# 执行方法2. 因为文件开头已经写了执行器类型,直接调用(./指当前目录,如有不理解请自行搜索)
./hello.sh
继续编辑hello.sh
文件,内容如下
#!/bin/bash
var_hello_str='Hello World!'
# 使用1. 不带花括号
echo $pick_hero
# 使用2. 带花括号(推荐写法)
echo ${pick_hero}
变量命名规则与大部分编程语言类似
以下是一些常用的Bash保留关键字:
if
, then
, else
, elif
, fi
:这些关键字用于条件判断。for
, do
, done
:这些关键字用于循环。while
, until
:这些关键字也用于循环。case
, esac
:这些关键字用于多路选择。function
:定义函数。select
:用于生成菜单。time
:用于计算命令或程序运行时间。{}
:用于命令组。[[ ]]
:用于条件表达式。(( ))
:用于算术运算。!
:用于逻辑非。in
:用于for循环中指定一个列表。break
和continue
:分别用于跳出循环和跳过当前循环迭代。return
:用于从函数中返回。exit
:用于退出脚本。以上是一些常见的Bash保留关键字,但并不全面,具体的关键字和用法可以查阅Bash的官方文档。
下面是变量其他写法一览
#!/bin/bash
# 定义并设置只读变量,只读变量不能被重新定义或删除
readonly my_name="chancel"
# 拼接字符串
str01="hello"
str02="world"
echo "${str01} ${str02}" # 用空格拼接两个字符串
# 定义数组
myArray=("x" "y" "z")
echo "${myArray[0]}" #取出第一个元素
echo "${myArray[*]}" # 取出所有元素
echo "${myArray[@]}" # 取出所有元素
# 遍历数组
for var in "${myArray[@]}"; do
echo "$var"
done
# 遍历数组并打印索引和元素
for i in "${!myArray[@]}"; do
printf "%s\t%s\n" "$i" "${myArray[$i]}"
done
# 使用while循环遍历数组
i=0
while [ $i -lt ${#myArray[@]} ]; do
echo "${myArray[$i]}"
((i++))
done
我们经常使用下面这种方法调用脚本
./xswl.sh -who chancel -why cxk
这种做法一般需要检查用户输入,下面是一个完整的方法
#!/bin/bash -e
show_help() {
echo "$0 [-h|-?|--help] [--who me] [--why hhh]"
echo "-h|-?|--help 显示帮助"
echo "--who 输入你是谁"
echo "--why 为什么笑"
}
while [[ $# -gt 0 ]]; do
case $1 in
-h | -\? | --help)
show_help
exit 0
;;
--who)
WHO="${2}"
shift
;;
--why)
WHY="${2}"
shift
;;
*)
echo -e "Error: $0 invalid option '$1'\nTry '$0 --help' for more information.\n" >&2
exit -1
;;
esac
shift
done
调用效果
$ ./xswl.sh -h
./xswl.sh [-h|-?|--help] [--who me] [--why hhh]
-h|-?|--help 显示帮助
--who 输入你是谁
--why 为什么笑
bash是如何控制流程的,参考下面的例子 if-else规则
if condition
then
command1
command2
...
commandN
fi
if-elseif-else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
一个简单的例子
#!/bin/bash -e
x=100
y=200
if [ $x == $y]
then
echo "x = y"
elif [ $x -gt $y ]
then
echo "x > y"
else
echo "x < y"
上面涉及到运算符,bash的运算符相对简单
参数 | 说明 |
---|---|
-eq | = |
-ne | != |
-gt | > |
-ge | >= |
-lt | =< |
-le | <= |
-z(字符串) | 字符串长度为零 |
-n(字符串) | 字符串长度不为零 |
下面是例子
#!/bin/bash
# 加减乘除运算
x=100
y=200
$z=$[x+y] #这语法有点奇怪,且实测等号两侧不可空格(写惯了c#可能很不习惯这种写法)
echo $z
# 字符串判断
x="hello"
y="hallo"
if test $x = $y
then
echo "字符串内容相同"
else
echo "字符串内容不同"
fi
到这写一个最基础的服务器备份脚本知识点基本都齐了,如果对其他语法点还感兴趣,可以参考下面进行学习
日常常见的语法还有下面这些
我的需求主要有以下2点
程序思路
于是经过上面的学习以及备份思路,你可以得到以下这份脚本,里面的所有知识点基本都在上面提到了,只有date函数没有提到(这个比较复杂,请自行搜索相关资料参阅)
#!/bin/bash
# author:chancel
# url:www.chancel.me
show_help() {
echo "$0 [-h|-?|--help] [--temp /tmp/_backup] [--target /opt/backup/] [--dbuser root] [--dbpasswd passwd] [--extra /opt]"
echo "-h|-?|--help 显示帮助"
echo "--temp 设置备份文件时的缓存目录"
echo "--target 设置备份文件的目标(存放)路径"
echo "--dbuser 设置mysql数据库用户名称"
echo "--dbpasswd 设置mysql数据库用户密码"
echo "--extra 额外需要备份的目录,以空格分开不同目录"
}
while [[ $# -gt 0 ]]; do
case $1 in
-h | -\? | --help)
show_help
exit 0
;;
--temp)
temp="${2}"
shift
;;
--target)
target="${2}"
shift
;;
--dbuser)
dbuser="${2}"
shift
;;
--dbpasswd)
dbpasswd="${2}"
shift
;;
--extra)
extra="${2}"
shift
;;
--)
shift
break
;;
*)
echo -e "错误: $0 无效操作 '$1'\n可输入命令 '$0 --help' 获取更多帮助.\n" >&2
exit -1
;;
esac
shift
done
echo "创建必要的文件夹"
mysql_backup_dir=$temp'/mysql_backup'
mkdir -p $mysql_backup_dir
new_backup_file_path=$temp"/`date +%Y%m%d`.tar.gz"
old_backup_file_path=$target"/`date -d -1day +%Y%m%d`.tar.gz"
echo "备份mysql数据库"
databases=`mysql -u$dbuser -p$dbpasswd -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`
for db in $databases; do
if [[ "$db" != "sentry" ]] && [[ "$db" != "information_schema" ]] && [[ "$db" != "performance_schema" ]] && [[ "$db" != "mysql" ]] && [[ "$db" != _* ]] ; then
echo "正在导出数据库$db"
mysqldump -u$dbuser -p$dbpasswd --databases $db > $mysql_backup_dir'/'`date +%Y%m%d`-$db.sql
fi
done
echo "正在删除上一次产生的备份包"
rm -f $old_backup_file_path
echo "创建备份文件"$new_backup_file_path
tar -zcvf $new_backup_file_path $mysql_backup_dir $extra
mv $new_backup_file_path $target
echo "删除临时文件夹"$temp
rm -rf $temp
echo "备份结束"
参考这份文档,根据你的需要自定修改你就可以快速得到一份备份脚本