一.shell脚本概述
1.Shell脚本的概念
将要执行的命令按顺序保存到一个文本文件
给该文件可执行权限
可结合各种Shell控制语句以完成更复杂的操作
2.Shell脚本应用场景
重复性操作
交互性任务
批量事务处理
服务运行状态监控
定时任务执行
3.Shell的作用
命令解释器,翻译官
介于系统内核与用户之间,复制解释命令行
4.编写shell脚本
使用vim文件编辑器
每行一条linux命令,按执行顺序一次编写
vim first.sh
多行注释也可以用下列方式表示
给脚本权限
chmod +x first.sh
执行脚本
[root@localhost ~]# ./first.sh
hello world!!
[root@localhost ~]# /root/first.sh
hello world!!
[root@localhost ~]# bash first.sh
hello world!!
[root@localhost ~]# sh first.sh
hello world!!
[root@localhost ~]#
说明
在没有权限的情况下使用bash,sh执行脚本
bash sh 是在新开的shell环境执行,执行完返回
bash 与sh ksh比较
bash优点 更高级 可以看到当前用户 支持快捷键 可以补全命令
bash -x 每一行检测调试
bash -n 只检查语法错误 检查指定哪行出错
5.管道和重定向
(1)管道操作
管道操作作为不同命令之间的协同工作提供了一种机制,位于管道符号“|”左侧的命令输出的结果,将作为右侧命令的输入(出来对象),同一行命令中可以使用多个管道。
[root@localhost ~]# df -hT
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root xfs 50G 5.3G 45G 11% /
devtmpfs devtmpfs 894M 0 894M 0% /dev
tmpfs tmpfs 910M 0 910M 0% /dev/shm
tmpfs tmpfs 910M 11M 900M 2% /run
tmpfs tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda1 xfs 1014M 179M 836M 18% /boot
/dev/mapper/centos-home xfs 247G 38M 247G 1% /home
tmpfs tmpfs 182M 8.0K 182M 1% /run/user/42
tmpfs tmpfs 182M 52K 182M 1% /run/user/0
/dev/sr0 iso9660 4.3G 4.3G 0 100% /run/media/root/CentOS 7 x86_64
[root@localhost ~]# df -hT | grep "/$" |awk '{print $6}'
11%
[root@localhost ~]#
(2)重定向操作
交互式硬件设备
标准输入:从键盘输入,设定键盘为输入设备
标准输出:通过显示器输出到屏幕
标准错误:当我执行一个命令时,显示器会把错误信息输出到屏幕
重定向操作
重定向输出 >是覆盖 ;>>是追加 ;1>正确输出
[root@localhost ~]# echo 1234 > 11.txt
[root@localhost ~]# cat 11.txt
1234
[root@localhost ~]# echo 1234 >> 11.txt
[root@localhost ~]# cat 11.txt
1234
1234
[root@localhost ~]# echo 1234 1> 11.txt
[root@localhost ~]# cat 11.txt
1234
[root@localhost ~]#
错误输入用2> :错误输入追加用2>>
[root@localhost ~]# ls
11.txt 1234.txt anaconda-ks.cfg expect.sh initial-setup-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]# ls xx
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# ls xx > 2.txt
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# ls xx >> 2.txt
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# cat 2.txt
[root@localhost ~]# ls xx 2> 2.txt
[root@localhost ~]# cat 2.txt
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# ls xx 2>> 2.txt
[root@localhost ~]# cat 2.txt
ls: 无法访问xx: 没有那个文件或目录
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]#
有正确输入也有错误输入
[root@localhost ~]# ls xx 11.txt
ls: 无法访问xx: 没有那个文件或目录
11.txt
[root@localhost ~]# ls xx 11.txt > 3.txt
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# cat 3.txt
11.txt
[root@localhost ~]# ls xx 11.txt 2> 3.txt >4.txt
[root@localhost ~]# cat 3.txt
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# cat 4.txt
11.txt
[root@localhost ~]#
输出不显示可以用混合输出 &> /dev/null
[root@localhost ~]# ls xx
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# ls xx &> /dev/null
[root@localhost ~]#
<是读取数据
[root@localhost ~]# cat 11.txt
1234
[root@localhost ~]# cat < 11.txt
1234
[root@localhost ~]#
二.shell脚本变量
1.自定义变量
(1)定义一个新变量
定义新变量并查看变量值
[root@localhost ~]# a=10
[root@localhost ~]# echo $a
10
[root@localhost ~]# a=114
[root@localhost ~]# echo $a
114
[root@localhost ~]# A=lisa
[root@localhost ~]# echo $A
lis
unset 取消变量
[root@localhost ~]# unset a
[root@localhost ~]# echo $a
[root@localhost ~]#
set 可以查看所有的变量
[root@localhost ~]# AA=wangwu
[root@localhost ~]# set | grep wangwu
AA=wangwu
[root@localhost ~]#
自定义变量只作用于当前环境
[root@localhost ~]# AA=wangwu
[root@localhost ~]# echo $AA
wangwu
[root@localhost ~]# bash
[root@localhost ~]# echo $AA
[root@localhost ~]#
(2)赋值时使用引号
单引号:允许通过$符号引用其他变量值
双引号:禁止引用其他变量值,$视为普通字符
反撇号:命令替换,提取命令执行后的输出结果
[root@localhost ~]# a=10
[root@localhost ~]# echo "$a"
10
[root@localhost ~]# echo '$a'
$a
[root@localhost ~]# echo \$a
$a
[root@localhost ~]# echo `date`
2021年 06月 14日 星期一 22:05:22 CST
[root@localhost ~]# a=$(date)
[root@localhost ~]# echo $a
2021年 06月 14日 星期一 22:22:18 CST
[root@localhost ~]# echo $(rpm -qf $(which rz))
lrzsz-0.12.20-36.el7.x86_64
[root@localhost ~]# rpm -ql $(rpm -qf $(which rz))
/usr/bin/rb
/usr/bin/rx
/usr/bin/rz
/usr/bin/sb
/usr/bin/sx
/usr/bin/sz
/usr/share/locale/de/LC_MESSAGES/lrzsz.mo
/usr/share/man/man1/rz.1.gz
/usr/share/man/man1/sz.1.gz
[root@localhost ~]#
(3)声明变量是整数类型的变量
[root@localhost ~]# declare -i int=10
[root@localhost ~]# echo $int
10
[root@localhost ~]# int=20
[root@localhost ~]# echo $int
20
[root@localhost ~]# int=xuxu
[root@localhost ~]# echo $int
0
[root@localhost ~]#
(4)定义变量为只读变量
[root@localhost ~]# a=wangwu
[root@localhost ~]# readonly a
[root@localhost ~]# echo $a
wangwu
[root@localhost ~]# a=lisi
bash: a: 只读变量
[root@localhost ~]#
[root@localhost ~]# unset a
bash: unset: a: 无法反设定: 只读 variable
(5)read命令也可以定义赋值变量
[root@localhost ~]# read name
zhangsan //这里会等待你输入变量
[root@localhost ~]# echo $name
zhangsan
[root@localhost ~]#
选项说明
-p 会提示输入
-n 指定最大输入的变量数
-s 私密静默,输入时不显示
(6)数值变量的运算
整数变量的运算
expr命令
expr 变量 运算符 变量
expr只识别整数,不是整数会进行取整
常用运算符
加法运算:+
减法运算:-
乘法运算:\ * 乘法需要用转义符
除法运算:/
求模(取余)运算:%
[root@localhost ~]# expr 1 + 1
2
[root@localhost ~]# expr 8 - 2
6
[root@localhost ~]# expr 4 * 3
expr: 语法错误
[root@localhost ~]# expr 4 \* 3
12
[root@localhost ~]# expr 10 / 3
3
[root@localhost ~]# expr 10 % 3
1
[root@localhost ~]#
[root@localhost ~]# a=10
[root@localhost ~]# b=3
[root@localhost ~]# expr $a + $b
13
[root@localhost ~]# expr $a - $b
7
[root@localhost ~]# expr $a \* $b
30
[root@localhost ~]# expr $a / $b
3
[root@localhost ~]# expr $a % $b
1
[root@localhost ~]#
[root@localhost ~]# echo $[2 + 2]
4
[root@localhost ~]# echo $[2 / 2]
1
[root@localhost ~]# echo $[2 % 2]
0
[root@localhost ~]# echo $[a + b]
13
[root@localhost ~]# echo $[a % b]
1
[root@localhost ~]#
let命令
a++ 表示 a=a+1
a-- 表示 a=a-1
[root@localhost ~]# a=10
[root@localhost ~]# echo $a
10
[root@localhost ~]# let a++
[root@localhost ~]# echo $a
11
[root@localhost ~]# let a--
[root@localhost ~]# echo $a
10
[root@localhost ~]# echo $[a++]
10
[root@localhost ~]# echo $a
11
[root@localhost ~]# echo $[++a]
12
[root@localhost ~]# echo $a
12
[root@localhost ~]#
bc计算器
[root@localhost ~]# bc //单独用bc是交互式页面
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
2.6+8.1
10.7
5.8*3
17.4
quit
[root@localhost ~]#
[root@localhost ~]# echo "2.5+8.4" | bc
10.9
[root@localhost ~]# echo "scale=3;10/3" | bc //区小数点后几位
3.333
[root@localhost ~]# echo $[2**8] //计算次方
256
[root@localhost ~]# let a=2**8
[root@localhost ~]# echo $a
256
[root@localhost ~]# echo "2^8" | bc //bc计算器计算次方
256
[root@localhost ~]#
2.特殊变量
(1)环境变量
env查看所有环境变量
查看单个
echo $PWD
自定义变量只作用于当前环境,要使其作用于全局要写入环境变量
aa=10
写入环境变量
vim /etc/profile
最后一行加入
export aa=10
vim /etc/profile
[root@localhost ~]# source /etc/profile //重新读入配置文件
[root@localhost ~]# echo $aa
10
[root@localhost ~]# bash
[root@localhost ~]# echo $aa
10
[root@localhost ~]#
export命令
为了使用户定义的变量在所有的子Shell环境中能够继续使用,减少重复设置工作,可以通过内部命令export将指定的变量导出为全局变量。用户可以同时指定多个变量名称作为参数(无须使用“$”符号),变量名之间以空格分隔,但是export命令只是临时的。
使用export 导出全局变量的同时,也可以为变量进行赋值,这样在新定义全局变量时就不需要提前进行赋值了
env查看用户当前环境变量export ABC=123
再次env就能看到了
export -n ABC取消定义的全局变量变成局部变量
[root@localhost ~]# bb=20
[root@localhost ~]# echo $bb
20
[root@localhost ~]# export bb
[root@localhost ~]# env | grep bb
bb=20
[root@localhost ~]#
查看当前bash层级
[root@localhost ~]# echo $SHLVL
9
[root@localhost ~]#
(2)位置变量
第一个位置变量为$1,第二个位置变量为$2,以此类推
vim test.sh
[root@localhost ~]# bash test.sh 8 6
14
[root@localhost ~]# bash test.sh 3 9
12
[root@localhost ~]#
(3)预定义变量
预定义变量是由Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。预定义变量使用“$”符号和另一个符号组合表示。
$? 上一条命令的结果 为0成功 非0不成功
$# 表示命令行中位置变量的个数
$$ 表示返回当前进程的进程号
$! 返回最后一个后台进程的进程号
$* 表示所有位置参数的内容,这些内容当做一个整体
$@ 显示全部内容 个体
$0 表示当前执行的脚本或程序的名称
[root@localhost ~]# ls
11.txt 1234.txt 2.txt 3.txt 4.txt anaconda-ks.cfg expect.sh initial-setup-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]# echo $?
0
[root@localhost ~]# ls xx
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# echo $?
2
[root@localhost ~]# echo $#
0
[root@localhost ~]# echo $*
[root@localhost ~]# echo $$
36682
[root@localhost ~]# echo $@
[root@localhost ~]# echo $!
[root@localhost ~]# sleep 100 &
[1] 38654
[root@localhost ~]# echo $!
38654
三.shell编程之条件语句
1.条件测试
(1)文件测试
文件测试指的是根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否存在,是否可读、可写、可执行等
选项:(主要是defrwx)
-d:测试是否为目录(Directory)
-e:测试目录或文件是否存在(Exist)
-f:测试是否为文件(File)
-L:测试是否为链接文件
-b:测试是否为设备文件
-c:测试是否为字符设备文件
-r:测试当前用户是否有权限读取(Read)
-w:测试当前用户是否有权限写入(Write)
-x:测试是否设置有可执行(Excute)权限
-s:测试存在且文件大小为空
[root@localhost ~]# [ -d /etc ] && echo y || echo n
y
[root@localhost ~]# [ -d /xxx ] && echo y || echo n
n
[root@localhost ~]# [ -f /xxx ] && echo y || echo n
n
[root@localhost ~]# [ -f /etc ] && echo y || echo n
n
[root@localhost ~]# [ -e /etc ] && echo y || echo n
y
[root@localhost ~]# [ -e /etc/xxx ] && echo y || echo n
n
[root@localhost ~]# [ -w /etc/ ] && echo y || echo n
y
[root@localhost ~]#
(2)整数值比较
整数值比较指的是根据给定的两个整数值,判断第一个数与第二个数的关系,如是否大于、等于、小于第二个数,实际应用非常广泛
例如用来判断已登录用户数量、开启进程数、磁盘使用率是否超标,以及软件版本号是否符合要求等
操作选项:
-eq:第一个数等于(Equal)第二个数。
-ne:第一个数不等于(Not Equal)第二个数。
-gt:第一个数大于(Greater Than)第二个数。
-lt:第一个数小于(Lesser Than)第二个数。
-le:第一个数小于或等于(Lesser or Equal)第二个数。
-ge:第一个数大于或等于(Greater or Equal)第二个数
[root@localhost ~]# [ 2 -eq 4 ] && echo y || echo n
n
[root@localhost ~]# [ 2 -gt 4 ] && echo y || echo n
n
[root@localhost ~]# [ 2 -lt 4 ] && echo y || echo n
y
[root@localhost ~]# [ 2 -eq 2 ] && echo y || echo n
y
[root@localhost ~]# [ 2 -ne 2 ] && echo y || echo n
n
[root@localhost ~]# [ 2 -ge 2 ] && echo y || echo n
y
[root@localhost ~]# [ 2 -le 2 ] && echo y || echo n
y
[root@localhost ~]#
(3)字符串比较
字符串你叫常用的操作选项
=:第一个字符串与第二个字符串相同
!=:第一个字符串与第二个字符串不相同,其中" ! “ 符号表示取反
-z:检查字符串是否为空,对于未定义或赋予空值的变量视为空串
-n:检测字符串是否为非空
[root@localhost ~]# test a == b
[root@localhost ~]# echo $?
1
[root@localhost ~]# test a != b
[root@localhost ~]# echo $?
0
[root@localhost ~]#
[root@localhost ~]# a=xuxu
[root@localhost ~]# echo $a
xuxu
[root@localhost ~]# [ -z $a ] && echo y || echo n
n
[root@localhost ~]# [ -n $a ] && echo y || echo n
y
[root@localhost ~]# [ -n xx ] && echo y || echo n
y
[root@localhost ~]#
[root@localhost ~]# [ a == b ] && echo y || echo n
n
[root@localhost ~]# [ a != b ] && echo y || echo n
y
[root@localhost ~]#
[root@localhost ~]# a=
[root@localhost ~]# [ -z $a ] && echo y || echo n
y
[root@localhost ~]# [ -n $a ] && echo y || echo n
y
[root@localhost ~]# [ -z "$a" ] && echo y || echo n
y
[root@localhost ~]# [ -n "$a" ] && echo y || echo n
n
[root@localhost ~]#
(4)逻辑测试
常用的测试操作符
-a或&&:逻辑与,“而且”的意思
-o或||:逻辑或,“或者”的意思·
!:逻辑否
[root@localhost ~]# ls
11.txt 1234.txt 2.txt 3.txt 4.txt anaconda-ks.cfg expect.sh initial-setup-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
[root@localhost ~]# ls ; date
11.txt 1234.txt 2.txt 3.txt 4.txt anaconda-ks.cfg expect.sh initial-setup-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
2021年 06月 15日 星期二 10:56:42 CST
[root@localhost ~]# ls xx ; date
ls: 无法访问xx: 没有那个文件或目录
2021年 06月 15日 星期二 10:56:50 CST
[root@localhost ~]# ls xx && date
ls: 无法访问xx: 没有那个文件或目录
[root@localhost ~]# ls xx || date
ls: 无法访问xx: 没有那个文件或目录
2021年 06月 15日 星期二 10:57:29 CST
[root@localhost ~]#
[root@localhost ~]# [ 8 -gt 2 -a 8 -gt 5 ] && echo y || echo n
y
[root@localhost ~]# [ 8 -gt 2 -a 8 -lt 5 ] && echo y || echo n
n
[root@localhost ~]# [ 8 -gt 2 -o 8 -lt 5 ] && echo y || echo n
y
[root@localhost ~]# [[ 8 -gt 2 && 8 -lt 5 ]] && echo y || echo n
n
[root@localhost ~]# [[ 8 -gt 2 || 8 -lt 5 ]] && echo y || echo n
y
[root@localhost ~]#
[root@localhost ~]# [[ abc == abc* ]] && echo y || echo n
y
[root@localhost ~]# [ abc == abc* ] && echo y || echo n
n
[root@localhost ~]# [ abc* == abc* ] && echo y || echo n
y
[root@localhost ~]#
2.if语句
(1)单分支结构
判断一个文件是不是脚本
(2)双分支结构
判断ip是否在线
(3)多分支结构
写一个判定成绩的脚本
判断一个用户是否有家目录(默认在/home下),有打印正常,没有询问是否删除,是就删除
四.shell脚本之case语句
1.case语句的结构
case语句主要适用于以下情况:某个变量存在多种取值,需要对其中的每一种取值分别执行不同的命令序列。
case 变量值 in
模式一)
命令序列1
;;
模式二)
命令序列2
;;
…
*)
默认命令序列
esac
2.case语句应用示例
vim fan.sh
[root@localhost ~]# bash fan.sh
请输入星期几:星期一
吃牛排
[root@localhost ~]# bash fan.sh
请输入星期几:周日
吃鲍鱼
[root@localhost ~]#
[root@localhost ~]# bash fan.sh
请输入星期几:八
输入错误
[root@localhost ~]#
五.shell脚本之循环语句
1.for循环语句
读取不通的变量值,用来逐个执行同一组命令
打印5遍hello的几种for循环方式
也可以引入位置参数
vim 6.sh
[root@localhost ~]# bash 6.sh hello world nihao wangwu lisi
hello
world
nihao
wangwu
lisi
[root@localhost ~]#
vim 7.sh
[root@localhost ~]# bash 7.sh hello world nihao wangwu lisi
hello
hello
hello
hello
hello
[root@localhost ~]#
2.while循环语句
重复测试某个条件,只要成立则反复执行
打印1到5
vim 8.sh
[root@localhost ~]# bash 8.sh
1
2
3
4
5
[root@localhost ~]#
3.until循环语句
重复测试某个条件,只要条件不成立则反复执行
计算从1加到100的和
vim qiuhe.sh
[root@localhost ~]# bash qiuhe.sh
5050
说明:
死循环
while true
until false
六.shell函数
将命令按格式卸载一起,以便可以重复的使用
shell函数的定义
基本格式
function 函数名(){
命令序列
return x
}
调用函数的方法
函数名 参数1 参数2
函数返回状态码
函数的最后一条命令的执行结果为返回码
return 指定返回码的值 范围是0-255
计算阶乘运用调用函数
七.shell数组
应用场景包括
获取数组长度
获取元素长度
遍历元素
元素切片
元素替换
元素删除
…
数组
a(1 2 3 4 5 )
数组内每一位对应一个下标
每一位的对应关系如下
a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=5
[root@localhost ~]# a=(1 2 3 4 5)
[root@localhost ~]# echo ${a[1]}
2
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5
[root@localhost ~]# echo ${a[@]}
1 2 3 4 5
[root@localhost ~]# echo ${#a[@]}
5
[root@localhost ~]#
[root@localhost ~]# fruit=([0]=apple [1]=orange [2]=banana)
[root@localhost ~]# echo ${fruit[*]}
apple orange banana
[root@localhost ~]# fruit[4]=tomato
[root@localhost ~]# echo ${fruit[*]}
apple orange banana tomato
[root@localhost ~]#
[root@localhost ~]# aa=( 1 2 lisi tomato)
[root@localhost ~]# echo ${aa[*]}
1 2 lisi tomato
list 列表
也可以把文件内容输出到列表
list= `cat 11.txt `
[root@localhost ~]# echo "1 2 3 4 5 6 7 8 " > 11.txt
[root@localhost ~]# cat 11.txt
1 2 3 4 5 6 7 8
[root@localhost ~]# list=`cat 11.txt`
[root@localhost ~]# echo ${list[*]}
1 2 3 4 5 6 7 8
[root@localhost ~]# list=`cat /etc/passwd`
[root@localhost ~]# list1=($list)
[root@localhost ~]# echo ${#list1[*]} //参数个数
103
元素切片
[root@localhost ~]# a=(1 2 3 4 5 6)
[root@localhost ~]# echo ${a[*]:1:3} //切1个,打印3个
2 3 4
[root@localhost ~]# echo ${a[*]:2:3} //切2个,打印3个
3 4 5
元素替换
[root@localhost ~]# a=(1 2 3 4 5 6)
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5 6
[root@localhost ~]# echo ${a[*]/6/16} //是临时的
1 2 3 4 5 16
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5 6
[root@localhost ~]# a[5]=16
[root@localhost ~]# echo ${a[*]}
1 2 3 4 5 16
[root@localhost ~]#