Shell语言
Bash脚本编程
Bash基本格式
[root@aarch64 ~]# cat > hello.sh << EOF
> #!/bin/bash
> echo "Hello,World~"
> EOF
[root@aarch64 ~]# chmod u+x hello.sh
[root@aarch64 ~]# ./hello.sh
Hello,World~
[root@aarch64 ~]# sh hello.sh
Hello,World~
变量说明
变量介绍
- 系统变量(
set
):$HOME
,$PWD
,$SHELL
,$USER
- 用户自定义变量
变量定义
- 变量名称可以由字母、数字和下划线组成。不能以数字开头
- 等号两侧不能有空格
- 变量名称一般习惯为大写
#!/bin/bash
#案例1:定义变量A
A=100
#输出变量需要加上$
echo A=$A
echo "A=$A"
#案例2:撤销变量A
unset A
echo "A=$A"
#案例3:声明静态的变量B=2,不能unset
readonly B=2
echo "B=$B"
#案例4:将指令返回的结果赋值给变量
C=`date`
echo "C=$C"
#旧版写法
D=$(cal)
echo "D=$D"
#新版写法
[root@aarch64 ~]# chmod +x var.sh
[root@aarch64 ~]# ./var.sh
A=100
A=100
A=
B=2
C=Tue Apr 13 23:00:42 CST 2021
D= April 2021
Su Mo Tu We Th Fr Sa
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
[root@aarch64 ~]#
设置环境变量
[root@aarch64 ~]# echo >> /etc/profile \
> export TOMCAT_HOME=/usr/local/tomcat
[root@aarch64 ~]# source /etc/profile
[root@aarch64 ~]# echo $TOMCAT_HOME
/usr/local/tomcat
多行注释
#这是单行注释
:<<!
这是多行注释
!
位置参数
参数 |
说明 |
$n |
n为数字,$0代表命令本身,{10} |
$* |
命令行中的所有参数,$*看作整体 |
$@ |
命令行中的所有参数,$@把参数区分对待 |
$# |
统计所有参数的个数 |
参考实例
[root@aarch64 ~]# cat myshell.sh
#!/bin/bash
echo "0=$0 1=$1 2=$2"
echo "所有的参数=$*"
echo "$@"
echo "参数的个数=$#"
[root@aarch64 ~]# chmod u+x myshell.sh
[root@aarch64 ~]# ./myshell.sh 111 222 333
0=./myshell.sh 1=111 2=222
所有的参数=111 222 333
111 222 333
参数的个数=3
预定义变量
参数 |
说明 |
$$ |
当前进程的进程号 |
$! |
后台运行的最后一个进程的进程号 |
$? |
最后一次执行命令的返回状态,值为0表示成功,值为1表示失败 |
参考实例
[root@aarch64 ~]# vim prevar.sh
[root@aarch64 ~]# cat prevar.sh
#!/bin/bash
echo "当前执行的进程id=$$"
#以后台的方式运行一个脚本,并获取他的进程号
/root/myshell.sh &
echo "最后一个后台方式允许的进程id=$!"
echo "执行的结果是=$?"
[root@aarch64 ~]# chmod u+x prevar.sh
[root@aarch64 ~]# ./prevar.sh
当前执行的进程id=399
最后一个后台方式允许的进程id=400
执行的结果是=0
[root@aarch64 ~]# 0=/root/myshell.sh 1= 2=
所有的参数=
参数的个数=0
运算符
[root@aarch64 ~]# vim oper.sh
[root@aarch64 ~]# cat oper.sh
#!/bin/bash
#案例1:计算(2+3)×4的值
#使用第一种方式
RES1=$(((2+3)*4))
echo "res1=$RES1"
#使用第二种方式(推荐使用)
RES2=$[(2+3)*4]
echo "res2=$RES2"
#使用第三种方式,需注意
#expr 1.反引号2.空格3.转义符4.临时变量
TEMP=`expr 2 + 3`
RES3=`expr $TEMP \* 4`
echo "res3=$RES3"
#案例2:请求出命令行的两个参数[整数]的和 20 50
SUM=`expr $1 + $2`
echo "sum=$SUM"
[root@aarch64 ~]# chmod u+x ./oper.sh
[root@aarch64 ~]# ./oper.sh 20 50
res1=20
res2=20
res3=20
sum=70
流程控制
条件判断
基本语法
[ condition ]
condition
前后必须要有空格
非空返回true
,否则返回false
0
返回true
,>1
返回false
#!/bin/bash
if [ 条件判断式 ];then
程序
fi
#!/bin/bash
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
fi
常用判断条件
判断语句 |
说明 |
= |
字符串比对 |
-lt |
小于 |
-le |
小于等于 |
-eq |
等于 |
-gt |
大于 |
-ge |
大于等于 |
-ne |
不等于 |
-r |
有读的权限 |
-w |
有写的权限 |
-x |
有执行的权限 |
-f |
文件存在且是常规文件 |
-e |
文件存在 |
-d |
文件存在且是一个目录 |
参考实例
[root@aarch64 ~]# vim if.sh
[root@aarch64 ~]# cat if.sh
#!/bin/bash
#案例1:"ok"是否等于"ok"
#判断语句:使用 =
if [ "ok" = "ok" ]
then
echo "equal"
fi
#案例2:23是否大于等于22
#判断语句:使用 -ge
if [ 23 -ge 22 ]
then
echo "大于"
fi
#案例3:/root/myshell.sh 目录中文件是否存在
#判断语句:使用 -f
if [ -f /root/myshell.sh ]
then
echo "存在"
fi
[root@aarch64 ~]# chmod u+x if.sh
[root@aarch64 ~]# ./if.sh
equal
大于
存在
[root@aarch64 ~]# vim ifcase.sh
[root@aarch64 ~]# cat ifcase.sh
#!/bin/bash
if [ $1 -ge 60 ]
then
echo "及格了"
elif [ $1 -lt 60 ]
then
echo "不及格"
fi
[root@aarch64 ~]# chmod u+x ifcase.sh
[root@aarch64 ~]# ./ifcase.sh 99
及格了
[root@aarch64 ~]# ./ifcase.sh 59
不及格
case语句
语法结构
case 变量 in
"值1")
程序/代码
;;
"值2")
程序/代码
;;
esac
参考实例
[root@aarch64 ~]# vim case.sh
[root@aarch64 ~]# cat case.sh
#!/bin/bash
#案例1:当命令行参数是1时,输出“周一”
#是2时,输出“周二”
#输入其他时,输出“other...”
case $1 in
"1")
echo "周一"
;;
"2")
echo "周二"
;;
*)
echo "other/^_^"
esac
[root@aarch64 ~]# chmod u+x case.sh
[root@aarch64 ~]# ./case.sh 1
周一
[root@aarch64 ~]# ./case.sh 2
周二
[root@aarch64 ~]# ./case.sh 3
other/^_^
for语句
语法结构
#基本语法1
for 变量 in 值1 值2 值3
do
程序/代码
done
#基本语法2
for ((初始值;循环控制条件;变量变化))
do
程序/代码
done
参考实例
#基本语法1案例
[root@aarch64 ~]# vim for1.sh
[root@aarch64 ~]# cat for1.sh
#!/bin/bash
#打印输入的参数,观察$*与$@的区别
for i in "$*"
do
echo "输入的数是:$i"
done
#这是$@的表示方法
echo "=========================="
for j in "$@"
do
echo "输入的数分别为:$j"
done
[root@aarch64 ~]# chmod u+x for1.sh
[root@aarch64 ~]# ./for1.sh 7890 7891 7893
输入的数是:7890 7891 7893
==========================
输入的数分别为:7890
输入的数分别为:7891
输入的数分别为:7893
#基本语法2案例
[root@aarch64 ~]# cat for2.sh
#!/bin/bash
#案例1:从1加到100的值输出显示
SUM=0
TMP=0
for (( i=1; i<=100; i++))
do
SUM=$[$SUM+$i]
TMP=`expr $TMP + $i`
done
echo "$SUM"
echo "$TMP"
[root@aarch64 ~]# ./for2.sh
5050
5050
while语句
基本语法
while [ 条件判断式 ]
do
程序/代码
done
参考实例
[root@aarch64 ~]# cat while.sh
#!/bin/bash
#案例1:从命令行输入一个数n,统计从1+...+n的值是多少?
SUM=0
i=0
while [ $i -le $1 ]
do
SUM=$[$SUM+$i]
i=$[$i+1]
done
echo "$SUM"
[root@aarch64 ~]# ./while.sh 100
5050
read读取控制台输入
基本语法
选项 |
说明 |
-p |
指定读取值时的提示符 |
-t |
指定读取值时等待的时间(秒) |
参考实例
[root@aarch64 ~]# vim read.sh
[root@aarch64 ~]# cat read.sh
#!/bin/bash
#案例1:读取控制台输入的NUM1的值
read -p "请输入第一个数:" NUM1
echo "你输入的数是:$NUM1"
#案例2:读取控制台输入的NUM2的值,在10秒内输入
read -t 10 -p "请输入第二个数:" NUM2
echo "你输入的数是:$NUM2"
[root@aarch64 ~]# chmod u+x read.sh
[root@aarch64 ~]# ./read.sh
请输入第一个数:233
你输入的数是:233
请输入第二个数:11223
你输入的数是:11223
函数
系统函数
#显示文件名
[root@aarch64 ~]# basename /home/jsc/sdn.txt
sdn.txt
#显示文件名去掉.txt
[root@aarch64 ~]# basename /home/jsc/sdn.txt .txt
sdn
#显示目录名
[root@aarch64 ~]# dirname /home/jsc/sdn.txt
/home/jsc
自定义函数
[root@aarch64 ~]# vim fun.sh
[root@aarch64 ~]# chmod u+x fun.sh
[root@aarch64 ~]# ./fun.sh
请输入一个数n1=100
请输入一个数n2=200
和是=300
[root@aarch64 ~]# cat fun.sh
#!/bin/bash
#案例1:计算输入的两个参数的和(动态获取),getSum
#定义函数
function getSum() {
SUM=$[$n1+$n2]
echo "和是=$SUM"
}
#输入两个值
read -p "请输入一个数n1=" n1
read -p "请输入一个数n2=" n2
#调用自定义函数
getSum $n1 $n2
Shell编程综合案例
- 每天凌晨2:30备份数据库
study
到/data/backup/db
- 备份开始和备份结束能够给出相应的提示信息
- 备份后的文件要求以备份时间为文件名,并打包成
.tar.gz
的形式,比如:2021-03-12_230201.tar.gz
- 在备份的同时,检查是否有10天前备份的数据库文件,如果有就将其删除
[root@aarch64 ~]# cd /usr/sbin/
[root@aarch64 sbin]# vim mysql_db_backup.sh
[root@aarch64 sbin]# chmod u+x mysql_db_backup.sh
[root@aarch64 sbin]# ./mysql_db_backup.sh
2021-04-16_221712
mysqldump: [Warning] Using a password on the command line interface can be insecure.
2021-04-16_221712/
2021-04-16_221712/2021-04-16_221712.sql.gz
备份数据库study成功^_^
[root@aarch64 sbin]# ll /data/backup/db/
total 4
-rw-r--r-- 1 root root 1046 Apr 16 22:17 2021-04-16_221712.tar.gz
[root@aarch64 sbin]# crontab -l
30 02 * * * /usr/sbin/mysql_db_backup.sh
源码
#!/bin/bash
#备份目录
BACKUP=/data/backup/db
#当前时间戳
DATETIME=$(date +%Y-%m-%d_%H%M%S)
echo "$DATETIME"
#数据库地址
HOST=localhost
#数据库用户名
DB_USER=root
#数据库密码
DB_PW=Mysql@3306
#备份的数据库名
DB_NAME=study
#判断备份目录是否存在,不存在则创建相应目录
[ ! -d "${BACKUP}/${DATETIME}" ] && mkdir -p "${BACKUP}/${DATETIME}"
#备份数据库
mysqldump -u${DB_USER} -p${DB_PW} --host=${HOST} -q -R --databases ${DB_NAME} | gzip > ${BACKUP}/${DATETIME}/$DATETIME.sql.gz
#处理.gz文件为.tar.gz后缀
cd ${BACKUP}
tar -zcvf ${DATETIME}.tar.gz ${DATETIME}
#删除备份前创建的目录
rm -rf ${BACKUP}/${DATETIME}
#删除10天以前备份的数据库文件
find ${BACKUP} -name "*.tar.gz" -atime +10 -exec rm -rf {} \;
echo "备份数据库${DB_NAME}成功^_^"