1 为什么要学习Shell编程
对于JavaEE和Python程序员来说,工作的需要,你的老大会要求你编写一些Shel脚本进行程序或者是服务器的维护,比如编写一个定时备份数据库的脚本.
对于大数据程序员来说,需要编写Shell程序来管理集群
2 Shell是什么
Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便裕兴程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。
3 Shell脚本的执行方式
1)sh脚本文件格式要求:
a.在内容的最前面以#!/bin/bash 开头
#!/bin/bash
b.脚本需要有可执行权限
如:创建一个hello.sh脚本
2)脚本的常用执行方式
a.方式1:
- 首先要赋予xx.sh脚本的+x权限:chmod 744 myShell.sh
chmod u+x hello.sh
- 执行脚本:./myShell.sh
./hello.sh
b.方式2:(sh+脚本)
- 说明:不用赋予+x权限,直接执行即可
sh hello.sh
4 shell的变量
1)shell变量的介绍:
Linux Shell的变量分为,系统变量和用户自定义变量
- 系统变量:$HOME、$PWD、$SHELL、$USER等等
- 显示当前shell中所有变量:set指令
set
2)shell变量的自定义
基本语法:
- 定义变量:
//等号=两边不能有空格
变量=值
- 撤销变量:
unset 变量
- 声明静态变量:
//注意:静态变量不能撤销set
readonly 变量
如:
3)定义变量的规则
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头
- 等号两侧不能有空格
- 变量名称一般习惯为大写
4)将命令的返回值赋给变量
``:反引号,表示执行里面的指令,并将结果赋值给定义的变量
//表示执行data指令,并将data指令执行的结果,赋值给变量A
A=`date`
$():等价于``
A=`date`
等价于
A=$(date)
如:
5)设置环境变量
基本语法:
- 将shell变量输出为环境变量(全局变量)
export 变量名=变量值
修改全局/环境变量后,需要刷新配置文件,才可以生效
- 让修改后的配置文件信息立即生效
source 配置文件
- 查询环境变量的值
echo $变量名
如:
6)多行注释
:<<!
需要注释的内容
!
7)位置参数变量
当我们执行一个shell脚本时,如果希望获取到命令行的参数信息就可以使用到位置参数变量。比如: ./myshell.sh 100 200,这个就是一个执行shell的命令行,可以在myshell脚本中传参100,200。
基本语法:
//n为数字,`$0`代表命令本身,`$1-$9`代表第一到第九个参数,10以上的参数需要用大括号包含,如`${10}`
$n
//这个变量代表命令行中所有的参数,`$*`把所有的参数看成一个整体
$*
//这个变量也代表命令行中所有的参数,不过`$@`把每个参数区分对待
$@
//这个变量代表命令行中所有参数的个数
$#
如:
8)预定义变量
shell设计者事先已经定义好的变量,可以直接在shell脚本中使用
基本语法:
//当前进程的进程号(PID)
$$
//后台运行的最后一个进程的进程号(PID)
$!
//最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确。
$?
//后台运行,在脚本文件后面加上 & 即是进行后台运行
脚本文件.sh &
5 运算符
1)算术运算符
在Shell中进行各种运算操作
语法:
$[运算式]
或
$((运算式))
或
expr m + n
注意:
- expr m + n,注意expr运算符间要有空格
- expr m - n
- expr \* / %,乘,除,取余
如:
2)比较运算符
字符串类型比较:
- =:字符串比较
整数类型比较:
- -lt:小于
- -le:小于等于
- -eq:等于
- -gt:大于
- -ge:大于等于
- -ne:不等于
6 条件判断
1)基本语法:
[ condition ]
- [ condition ],注意condition前后有空格!
- 非空返回true,可使用$?验证(0为true,>1为false)
2)字符串比较判断
如:判断ok是否等于ok,等于输出相等
if [ "ok" = "ok" ]
then
echo "相等"
fi
3)数值比较判断
如:判断12是否大于9,大于输出大于
if [ 12 -gt 9 ]
then
echo "大于"
fi
4)按照文件权限进行判断
- -r:有读的权限
- -w:有写的权限
- -x:有执行的权限
如:判断是否对a.txt有写的权限,有写的权限会输出有写的权限
if [ -w a.txt ]
then
echo "有写的权限"
fi
其他同理
5)按照文件类型进行判断
- -f:文件存在并且是一个常规的文件
- -e:文件存在
- -d:文件存在并且是一个目录
如:判断a.txt文件是否存在,存在,在控制台输出文件存在
if [ -e a.txt ]
then
echo "文件存在"
fi
其他同理
7 流程控制
1)if语句
基本语法:
- 单分支
if [ 条件判断式 ]
then
程序
fi
- 多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
fi
2)case语句
基本语法:
case $变量名 in
“值1”)
变量匹配值1,则执行这里
;;
“值2”)
变量匹配值2,则执行这里
;;
…省略其他分支…
*)
如果变量的值都不匹配,则执行这里
;;
esac
3)for循环
基本语法1:
for 变量 in 值1 值2 值3…
do
执行的代码
done
基本语法2:
for ((初始值;循环控制条件;变量变化))
do
执行的代码
done
案例1:循环输出填写的参数
for $A in $@
do
echo $A
done
案例2:求和:求1-10相加的总和
4)while循环
基本语法1:
while [ 条件判断式 ]
do
执行的程序
done
注意: [ 条件判断式 ] :[]和里面的条件判断式之间有空格
8 read读取控制台的输入
基本语法:
read [选项] (参数)
选项:
- -p:指定读取值时的提示符
- -t:指定读取值时等待的时间(秒),如果没有在指定的时间内输入,就不再等待了。
参数:
- 变量:指定读取值的变量名
案例:读取控制台输入的一个NUM值,要求在10秒输入,10不输入,就默认退出
read -p "请输入一个数字=" -t 10s NUM
echo $NUM
9 函数
1)系统函数
basename函数
- 返回完整路径最后/的部分,常用于获取文件名
语法:
basename [pathname] [suffix]
- basename命令会删掉所有的前缀包括最后一个/
- 选项:suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
案例1:
basename /aa/bb/cc/a.txt
得到a.txt字符串
案例2:
basename /aa/bb/cc/a.txt .txt
得到去掉后缀的文件名
dirname函数
- 返回完整路径最后/的前面的部分,常用于返回路径部分
语法:
dirname 文件绝对路径
- 从给定的包含文件名的绝对路径中返回目录部分
案例:
dirname /aa/bb/cc/a.txt
得到路径:/aa/bb/cc
2)自定义函数
基本语法:
function 函数名(){
执行语句
[return int;] //有返回值的时候
}
调用函数语法:
函数名 参数
如:编写一个函数计算两个数的和
10 Shell编程综合案例
1)需求分析:
- 每天凌晨2:10备份数据库atguiguDB到/data/backup/db
- 备份开始和备份结束能够给出相应的提示信息
- 备份后的文件要求以备份时间为文件名,并打包成.tar.gz的形式,比如:2018-03-12_230201.tar.gz
- 在备份的同时,检查是否有10天前备份的数据库文件,如果有就将其删除。
2)实现流程
实现流程如下:
- 先创建一个shall.sh脚本文件,用于实现数据库的备份和备份文件的删除,以及提示
- 使用crond定时器来定时调用该脚本文件
3)实现
编写脚本文件
先编写脚本文件mysql_rjx.sh
//进入到/sbin目录
cd /sbin
//创建,并编辑.sh脚本文件
vim mysql_rjx.sh
编辑脚本文件内容
#!/bin/bash
#备份目录
BACKUP=/data/backup/db
#获取当前时间
DATETIME=`date "+%Y-%m-%d_%H%M%S"`
echo $DATETIME
#数据库访问地址
HOST=localhost
#数据库用户名
DB_USER=root
#数据库密码
DB_PW=rjx666aaa
#需要备份的数据库
DATABASE=rjxedu
#创建备份目录,如果目录不存在,就创建
if [ ! -d "$BACKUP/$DATETIME" ]
then
mkdir -p $BACKUP/$DATETIME
fi
#开始备份数据库
mysqldump -u$DB_USER -p$DB_PW --host=$HOST -q -R --databases $DATABASE | gzip > $BACKUP/$DATETIME/$DATETIME.sql.gz
#将文件打包为.tar.gz格式
cd $BACKUP
tar -zcvf $DATETIME.tar.gz $DATETIME
#删除.sql.gz的文件及其父目录
rm -rf $DATETIME
#删除10天前的备份文件
find $BACKUP -atime +10 -name "*.tar.gz" -exec rm -rf {} \;
echo "备份数据库$DATABASE 成功"
创建定时器,执行脚本文件
crontab -e
并编辑
30 2 * * * /usr/sbin/mysql_rjx.sh
示意图
指令解释:
#开始备份数据库
mysqldump -u$DB_USER -p$DB_PW --host=$HOST -q -R --databases $DATABASE | gzip > $BACKUP/$DATETIME/$DATETIME.sql.gz
#删除10天前的备份文件
find $BACKUP -atime +10 -name "*.tar.gz" -exec rm -rf {} \;