shell编程

shell编程

shell 是一个命令行解释器,他为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell 来启动、挂起、停止甚至是编写一些程序

shell 脚本的执行方式

脚本格式要求:

  • 脚本以#!/bin/bash开头
  • 脚本需要有可执行权限
[ylq@rootylq shell]$ cat hello.sh
#!/bin/bash
echo "hello,world"

以脚本的绝对路径或相对路径执行shell

[ylq@rootylq shell]$ vim hello.sh
[ylq@rootylq shell]$ ./hello.sh
-bash: ./hello.sh: Permission denied
[ylq@rootylq shell]$ ll
total 4
-rw-rw-r-- 1 ylq ylq 31 Jan 18 10:59 hello.sh
[ylq@rootylq shell]$ chmod u+x hello.sh 
[ylq@rootylq shell]$ ./hello.sh
hello,world

用sh+脚本执行

[ylq@rootylq shell]$ sh hello.sh 
hello,world

shell的变量

  • Linux Shell 中的变量分为,系统变量和用户自定义变量

系统变量

$HOME, $PWD ,$SHELL, $USER[ylq@rootylq shell]$ echo $HOME
/home/ylq
[ylq@rootylq shell]$ echo $home

[ylq@rootylq shell]$ echo $PWD
/home/ylq/shell
[ylq@rootylq shell]$ echo $USER
ylq

  • 可通过set指令查看所有的系统变量
[ylq@rootylq shell]$ set |more

自定义变量

定义变量

​ 变量名=值

撤销变量

​ unset 变量

声明静态变量

​ readonly 变量,注意不能unset


#!/bin/bash

#定义变量
A=100
#输出变量需要加上$
echo A=$A
echo "A=$A"

#撤销变量A
unset A
echo A=$A

#声明静态变量,不能unset
readonly B=2
echo "B=$B"
unset B

[ylq@rootylq shell]$ ./var.sh 
A=100
A=100
A=
B=2
./var.sh: line 16: unset: B: cannot unset: readonly variable


shell 变量命名规范

  • 变量名称可以由字母、数字和下划线组成,但不能以数字作为开头
  • 等号两侧不能由空格
  • 变量名称一般习惯为大写

将命令的返回值赋给变量

A=`date`
A=$(date)
C=`date`
echo C=$C

D=$(date)
echo D=$D
[ylq@rootylq shell]$ ./var.sh 
A=100
A=100
A=
B=2
C=Wed Jan 18 11:26:38 CST 2023
D=Wed Jan 18 11:26:38 CST 2023

设置环境变量

基本语法

  • export 变量名=变量值 (功能描述:将shell变量输出为环境变量/全局变量)
  • source 配置文件 (功能描述:让修改后的配置信息立即生效)
  • echo $变量名 (功能描述:查询环境变量的值)

设置环境变量,可以使得多个函数共享变量

#定义一个环境变量
export YLQPATH=/home/ylq
[root@rootylq ~]# vim /etc/profile
[root@rootylq ~]# exco $YLQPATH
-bash: exco: command not found
[root@rootylq ~]# echo $YLQPATH

[root@rootylq ~]# source /etc/profile
[root@rootylq ~]# echo $YLQPATH
/home/ylq

shell 脚本的多行注释

:<<!
注释内容 
!

位置参数变量

当执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量

基本语法

  • $n
n代表数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号表示,如${10}
  • $* 这个变量代表命令行中的所有参数,把所有的参数看成一个整体
  • $@ 代表命令行中所有的参数,但把每个参数区分对待
  • $# 代表命令行中所有参数的个数
#!/bin/bash
echo "$0 1=$! 2= $2"
echo "所有参数=$*"
echo$@echo "参数个数=$#"

[root@rootylq shell]# chmod u+x myshell.sh 
[root@rootylq shell]# ./myshell.sh 100 200
./myshell.sh 1= 2= 200
所有参数=100 200
“100 200”
参数个数=2
[root@rootylq shell]# 

预定义变量

就是shell 设计者事先已经定义好的变量,可以直接在shell 脚本中使用

基本语法:

  • $$ 当前进程的进程号
  • $! 后台运行的最后一个进程的进程好
  • $? 最后一次执行的命令返回状态,如果这个变量的值为0。证明上一个命令正确;如果这个变量的值非0,则证明上一个命令执行不正确
#!/bin/bash

echo "当前执行的进程id=$$"

#以后台方式运行一个脚本,并获取他的进程号
/home/ylq/shell/myshell.sh &
echo "最后一个后台方式运行的子进程i=$!"
echo “执行结果是=$?
[root@rootylq shell]# chmod u+x preVAr.sh 
[root@rootylq shell]# ./pre
-bash: ./pre: No such file or directory
[root@rootylq shell]# ./preVAr.sh 
当前执行的进程id=18024
最后一个后台方式运行的子进程i=18025
“执行结果是=0[root@rootylq shell]# /home/ylq/shell/myshell.sh 1= 2= 
所有参数=
“”
参数个数=0
^C

shell 运算符

如何在shell中使用各自运算操作符

基本语法

$((运算式))或$[运算式]或expr m + n
  • expr 运算符之间要有空格,如果需要将expr的结果赋给某个变量,使用``
  • expr m - n
expr \*,/,% 乘,除,取余
[root@rootylq shell]# ./oper.sh 30 40
RES1=20
RES2=20
RES3=20
SUM=70
[root@rootylq shell]# cat oper.sh 
#!/bin/bash
#计算(2+3)*4 的值

#使用第一种方法

RES1=$(((2+3)*4))
echo "RES1=$RES1"

#使用第二种方式

RES2=$[(2+3)*4]
echo "RES2=$RES2"

#使用第三种方式 expr
TEMP=`expr 2 + 3`
RES3=`expr $TEMP \* 4`
echo "RES3=$RES3"


SUM=$[$1+$2]
echo "SUM=$SUM"

shell 条件判断

基本语法

[ condition ] 注意condition 前后都需要有空客

#非空返回true ,可使用$? 验证(0为true,>1为false)

判断语句

  • = 字符串比较
  • 两个整数的比较
    • -lt 小于
    • -le 小于等于 little equal
    • -eq 等于
    • -gt 大于等于
    • -ne 不等于
  • 按照文件权限进行判断
    • -r 有读权限
    • -w 有写权限
    • -x 有执行权限
  • 按照文件类型进行判断
    • -f 文件存在并且是一个常规的文件
    • -e 文件存在
    • -d 文件存在并是一个目录
[root@rootylq shell]# ./ifdemo.sh 
equal
23大于22
文件存在
[root@rootylq shell]# cat ifdemo.sh 
#!/bin/bash
#判断字符串是否相同
if [ "ok" = "ok" ]
then
	echo "equal"
fi


#判断23是否发育22

if [ 23 -ge 22 ]
then 
	echo "23大于22"
fi

#判断文件目录中文件是否存在

if [ -f /home/ylq/shell/myshell.sh ]
then 
	echo "文件存在"
fi

if [ ]
then
	echo "看我存在不"
fi


shell 流程控制

if 单分支与多分支

单分支

if [ ]
then
	echo "看我存在不"
fi

多分支

[root@rootylq shell]# chmod u+x ifcase.sh 
[root@rootylq shell]# ./ifcase.sh 70
及格了,哥们
[root@rootylq shell]# ./ifcase.sh 59
不及格,回家有你好果子吃
[root@rootylq shell]# cat ifcase.sh 
#!/bin/bash

if [ $1 -ge 60 ]
then 
	echo "及格了,哥们"

elif [ $1 -lt 60 ]
then 
	echo "不及格,回家有你好果子吃"
fi

[ 条件判断式 ],中括号和条件判断式之间必须要有空格

case 语句

case $变量名 in

“值1”)

程序1

;;

“值2”

程序2

;;

esac

[root@rootylq shell]# chmod u+x casedemo.sh 
[root@rootylq shell]# ./casedemo.sh 1
Monday
[root@rootylq shell]# ./casedemo.sh 2
Tuesday
[root@rootylq shell]# ./casedemo.sh 3
Wednesay
[root@rootylq shell]# ./casedemo.sh 4
Other...
[root@rootylq shell]# cat casedemo.sh 
#!/bin/bash
case $1 in 
"1")
echo "Monday"
;;
"2")
echo "Tuesday"
;;
"3")
echo "Wednesay"
;;
*)
echo "Other..."
;;
esac


for循环

基本语法1:

for 变量 in 值1 值2 …

do

程序

done

基本语法2

for ((初始值;循环控制条件;变量变化))

do

程序

done

[root@rootylq shell]# ./fordemo.sh 100 200 300
测试*
num is 100 200 300
*******************************
测试@
num@ is 100
num@ is 200
num@ is 300
./fordemo.sh: line 21: echo*********************************************: command not found
测试基本语法,打印1~10
SUM=1
SUM=3
SUM=6
SUM=10
SUM=15
SUM=21
SUM=28
SUM=36
SUM=45
SUM=55
[root@rootylq shell]# cat fordemo.sh 
#!/bin/bash

#$*将输入的参数当作一个整体,所以只会输出一句话
echo "测试*"
for i in "$*"
do 
	echo "num is $i"
done

#$@ 将输入的参数分别对待,有几个参数九江输出几句话
echo "*******************************"

echo "测试@"

for i in "$@"
do 
	echo "num@ is $i"
done


echo"*********************************************"
echo "测试基本语法,打印1~10"


SUM=0
for(( i=1; i<=10; i++))
do
	SUM=$[ $SUM+$i ]
	echo "SUM=$SUM"
done


while 循环

while [ 条件判断式 ]

do

​ 程序

done

[root@rootylq shell]# ./whiledemo.sh 100
执行结果=5050
[root@rootylq shell]# ./whiledemo.sh 10
执行结果=55
[root@rootylq shell]# cat whiledemo.sh 
#!/bin/bash
SUM=0
i=0

while [ $i -le $1 ]
do 
 	SUM=$[ $SUM+$i ]
#i自增
	i=$[ $i+1 ]
done
echo "执行结果=$SUM"


read 读取控制台输入

read(选项)(参数)

选项:

  • -p: 指定读取值时的提示符

  • -t: 指定读取值时的等待时间(秒),如果没有在指定的时间内输入,就不再等待了

参数:

  • 指定读取值的变量名
[root@rootylq shell]# vim readdemo.sh 
[root@rootylq shell]# ./readdemo.sh 
请输入一个数NUM1=10
输入的值是:10
请在10秒内输入一个数NUM2= 20
输入的值是NUM2=20
[root@rootylq shell]# ./readdemo.sh 
请输入一个数NUM1=10
输入的值是:10
请在10秒内输入一个数NUM2= 输入的值是NUM2=
[root@rootylq shell]# cat readdemo.sh 
#!/bin/bash

read -p "请输入一个数NUM1=" NUM1
echo "输入的值是:$NUM1"


read -t 10 -p "请在10秒内输入一个数NUM2= " NUM2
echo "输入的值是NUM2=$NUM2"
	

函数

shell函数可以有自定义函数,也可以有系统函数

系统函数

basename

返回完整路径/后的部分,常用于获取文件名

basename[ pathname ] [ suffix ]

basename 命令会删掉所有的后缀包括最后一个/字符,将字符串显示出来

suffix为后缀,如果suffix被制定了,basename会将pathname或string 的suffix去掉

[root@rootylq shell]# clear
[root@rootylq shell]# basename /home/ylq/shell/myshell.sh
myshell.sh
[root@rootylq shell]# basename /home/ylq/shell/myshell.sh .txt
myshell.sh
[root@rootylq shell]# 

dirname

功能:返回完整路径最后/的前面部分,常用于返回路径部分

dirname 文件绝对路径

​ 功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录部分)

[root@rootylq shell]# dirname /home/ylq/shell/myshell.sh 
/home/ylq/shell
[root@rootylq shell]# 

自定义函数

[ function ] funname [()]

{

​ Action;

​ [return int;]

}

调用直接写函数名: funname [值]

[root@rootylq shell]# ./functiondemo.sh 
请输入n1=10
情输入n2=20
SUM is 30
[root@rootylq shell]# cat functiondemo.sh 
#!/bin/bash
#定义函数 getSum
function getSum(){
	SUM=$[ $n1+$n2 ]
	echo "SUM is $SUM"
}

#输入两个值
read -p "请输入n1=" n1
read -p "情输入n2=" n2


#调用自定义函数
getSum $n1 $n2



shell 编程综合案例

备份数据库:

  • 每天凌晨2:30备份数据库
  • 备份开始和结束能够给出提示
  • 备份文件要求以备份时间为文件名,并打包成.tar.gz形式
  • 备份同时检查,是否有10天前的备份数据库文件,如果存在则删除
[root@rootylq ~]# crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
[root@rootylq ~]# crontab -l
30 2 * * * /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=Ylq1368670840!
#要备份的数据库
DATABASE=aliyun


#创建备份目录,如果不存在则创建
[ ! -d "${BACKUP}/${DATETIME}" ] && mkdir -p "${BACKUP}/${DATETIME}" 

#开始备份数据库
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} 

#删除对应的备份目录
rm -rf ${BACKUP}/${DATETIME}

#删除10天前的备份
find ${BACKUP} -atime +10 -name "*.tar.gz" -exec rm -rf {} \;
echo "备份数据库${DATABASE}成功-"


你可能感兴趣的:(Linux,linux,bash,运维)