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:定义变量AA=100#输出变量需要加上$echo A=$Aecho "A=$A"#案例2:撤销变量Aunset Aecho "A=$A"#案例3:声明静态的变量B=2,不能unsetreadonly B=2echo "B=$B"#案例4:将指令返回的结果赋值给变量C=`date`echo "C=$C"#旧版写法D=$(cal)echo "D=$D"#新版写法
[root@aarch64 ~]# chmod +x var.sh [root@aarch64 ~]# ./var.sh A=100A=100A=B=2C=Tue Apr 13 23:00:42 CST 2021D= April 2021 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 1011 12 13 14 15 16 1718 19 20 21 22 23 2425 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/bashecho "0=$0 1=$1 2=$2"echo "所有的参数=$*"echo "$@"echo "参数的个数=$#"[root@aarch64 ~]# chmod u+x myshell.sh [root@aarch64 ~]# ./myshell.sh 111 222 3330=./myshell.sh 1=111 2=222所有的参数=111 222 333111 222 333参数的个数=3
预定义变量
| 参数 |
说明 |
| $$ |
当前进程的进程号 |
| $! |
后台运行的最后一个进程的进程号 |
| $? |
最后一次执行命令的返回状态,值为0表示成功,值为1表示失败 |
参考实例
[root@aarch64 ~]# vim prevar.sh [root@aarch64 ~]# cat prevar.sh #!/bin/bashecho "当前执行的进程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 50SUM=`expr $1 + $2`echo "sum=$SUM"[root@aarch64 ~]# chmod u+x ./oper.sh [root@aarch64 ~]# ./oper.sh 20 50res1=20res2=20res3=20sum=70
流程控制
条件判断
基本语法
[ condition ]
condition前后必须要有空格
非空返回true,否则返回false
0返回true,>1返回false
#!/bin/bashif [ 条件判断式 ];then程序fi
#!/bin/bashif [ 条件判断式 ]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#判断语句:使用 -geif [ 23 -ge 22 ]then echo "大于"fi#案例3:/root/myshell.sh 目录中文件是否存在#判断语句:使用 -fif [ -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/bashif [ $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 3other/^_^
for语句
语法结构
#基本语法1for 变量 in 值1 值2 值3do程序/代码done#基本语法2for ((初始值;循环控制条件;变量变化))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=0TMP=0for (( i=1; i<=100; i++))do SUM=$[$SUM+$i] TMP=`expr $TMP + $i`done echo "$SUM" echo "$TMP"[root@aarch64 ~]# ./for2.sh 50505050
while语句
基本语法
while [ 条件判断式 ]do程序/代码done
参考实例
[root@aarch64 ~]# cat while.sh #!/bin/bash#案例1:从命令行输入一个数n,统计从1+...+n的值是多少?SUM=0i=0while [ $i -le $1 ]do SUM=$[$SUM+$i] i=$[$i+1]done echo "$SUM"[root@aarch64 ~]# ./while.sh 1005050
read读取控制台输入
基本语法
| 选项 |
说明 |
| -p |
指定读取值时的提示符 |
| -t |
指定读取值时等待的时间(秒) |
参考实例
[root@aarch64 ~]# vim read.sh[root@aarch64 ~]# cat read.sh #!/bin/bash#案例1:读取控制台输入的NUM1的值read -p "请输入第一个数:" NUM1echo "你输入的数是:$NUM1"#案例2:读取控制台输入的NUM2的值,在10秒内输入read -t 10 -p "请输入第二个数:" NUM2echo "你输入的数是:$NUM2"[root@aarch64 ~]# chmod u+x read.sh [root@aarch64 ~]# ./read.sh 请输入第一个数:233你输入的数是:233请输入第二个数:11223你输入的数是:11223
函数
系统函数
#显示文件名[root@aarch64 ~]# basename /home/jsc/sdn.txtsdn.txt#显示文件名去掉.txt[root@aarch64 ~]# basename /home/jsc/sdn.txt .txtsdn#显示目录名[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=" n1read -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_221712mysqldump: [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 -l30 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}成功^_^"