• 信号捕捉 陷阱
• trap‘触发指令’信号
进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
• trap ‘’ 信号
忽略信号的操作
• trap ‘-’ 信号
恢复原信号的操作
• trap -p
列出自定义信号操作
前面信号组合操作。
• trap finish EXIT
当脚本退出时,执行finish函数 避免异常退出。
• trap -p 查看信号工作状态
• 数组 :就是数据的集合,把相关性的数据放在一个集合里。可以放很多元
素,用索引或下标来表示,以数字形式编号。
- 数组名和索引
• 索引:编号从0开始,属于数值索引 (0-4)普通数组
• 注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,
bash4.0版本之后开始支持 如:字母、数字、混合使用与众不同,任意格式关
联数组。
bash --version 查看版本
• bash的数组支持稀疏格式(索引不连续)
• 稀疏文件:文件的实际大小和存在磁盘上显示的不同。
创建一个稀疏格式的文件,空洞文件。
Seek 跳过的是前100M,创建的是200M的文件。真正磁盘占用100M,真正的数
据是1M,显示的是200M,其他空间都是空的。
• 声明数组:
declare -a ARRAY_NAME 普通数组 可以不声明,但是只能是普通数组。
declare -A ARRAY_NAME 关联数组 先关联后使用。关联数组必须先声明,后
使用。
注意:两者不可相互转换 创建之后不可转换。
• 数组赋值
• 数组元素的赋值
(1) 一次只赋值一个元素
ARRAY_NAME[INDEX]=VALUE
weekdays[0]=“Sunday”
weekdays[4]=“Thursday”
Unset +数组名[编号]删除索引
(2) 一次赋值全部元素
ARRAY_NAME=(“VAL1” “VAL2” “VAL3” …)
数组一次性赋值,ls 先数列在数行。
(3) 只赋值特定元素
ARRAY_NAME=([0]=“VAL1” [3]=“VAL2” …)
(4) 交互式数组值对赋值
read -a ARRAY
• 显示所有数组:declare -a
declare -A +数组名 声明关联数组 必须先声明后使用 想实现键值对的情况下使用关联数
组。
不声明不同的索引第二个会覆盖掉第一个。
• 引用数组
• 引用数组元素
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下标为0的元素
• 引用数组所有元素
${ARRAY_NAME[]}
${ARRAY_NAME[@]}
• 数组的长度(数组中元素的个数)
${#ARRAY_NAME[]}
${#ARRAY_NAME[@]}
• 删除数组中的某元素:导致稀疏格式
unset ARRAY[INDEX]
• 删除整个数组
unset ARRAY
数组是临时性的,退出之后就没有了。
额外知识点(便利:对目标逐个的进行操作,提取元素之类的大概这个意思)
• 数组数据处理
• 引用数组中的元素:
数组切片:
${ARRAY[@]:offset:number}
offset 要跳过的元素个数
number 要取出的元素个数
取偏移量之后的所有元素
A
R
R
A
Y
[
@
]
:
o
f
f
s
e
t
•
向
数
组
中
追
加
元
素
:
A
R
R
A
Y
[
{ARRAY[@]:offset} • 向数组中追加元素: ARRAY[
ARRAY[@]:offset•向数组中追加元素:ARRAY[{#ARRAY[*]}]=value
• 关联数组:
declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]=‘val1’ [idx_name2]='val2‘…)
注意:关联数组必须先声明再调用
跳过两个取3个
跳过2个取后面的所有
字符串切片写法,要有空格。
普通数组追加元素,数组的个数做为下标对value赋值
生成10个随机数保存于数组中,并找出其最大值和最小值 !
用0的话可以对应编号,下标编号最小为0。
数组可以代替键值对的赋值,数组可以用来表示行号编号和列号编号
表示数字在第几行第几列。
1 2 3
4 5 6
7 8 9
matrix[11]=1 11代表第一行第一列
matrix[12]=2 12代表第一行第二列
将下图所示,实现转置矩阵matrix.sh
1 2 3 1 4 7
4 5 6 ===> 2 5 8
7 8 9 3 6 9
2、3、4、6、7、8行列对调,1、3、5不变。
2变为第一列第二行
3变为第一列第三行
4变为第二列第一行
6变为第二列第三行
7变为第三列第一行
8变为第三列第二行
冒泡法:
字符串切片
从一个字符串中取出其中的一部分。
• ${#var}:返回字符串变量var的长度
设定一个字符串变量,并取出其长度。
• ${var:offset}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字 符开始,到最后的部
分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
汉字也是表示为1个字符。
• ${var:offset:number}:返回字符串变量var中从第offset个字符后(不包括第offset个 字符)的字符开始,长度
为number的部分
跳过两个取三个
• ${var: -length}:取字符串的最右侧几个字符
注意:冒号后必须有一空白字符
• ${var:offset:-length}:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
• 抛头去尾。
•
• ${var: -length:-offset}:先从最右侧向左取到length个字符开始,再向右取到距离最
右侧offset个字符之间的内容
注意:-length前空格
从后往前数N个再从后往前数去掉N个保留去除后的剩余值,前面的长度一定要大于后面的数字,否则会显
示错误。这个写法对shell版本有要求,有的不支持。
• 字符串处理
• 基于模式取子串
${var#word}:其中word可以是指定的任意字符 功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删 除字符串开头至第
一次出现word字符串(含)之间的所有字符 从左到右查找string变量存储的字符串中,第一次出现的 : 删 除字符串开头至第一次出现 :
字符串(含)之间的所有字符。不是贪婪模式,找到一个之后不会继续往下寻找。
${var##word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后 一次由word指定的
字符之间的所有内容
找到最后一个冒号结束,删除冒号之前所有内容。
• 示例:
file=“var/log/messages”
${file#/}: log/messages
${file##/}: messages
• 字符串处理
• ${var%word*}:其中word可以是指定的任意字符 功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删 除字符串最后一 个
字符向左至第一次出现word字符串(含)之间的所有字符
file="/var/log/messages"
${file%/}: /var/log
从右往左查找并删掉第一个冒号之后的内容停止。(不是贪婪模式)
• ${var%%word}:同上,只不过删除字符串最右侧的字符向左至最后一次出现 word字符之间的所有
字符
从右往左查找删掉冒号之后的内容继续寻找直到没有冒号为止。
• 示例: url=http://www.magedu.com:8080
${url##:} 8080
${url%%:} http
字符串搜索替代
• 字符串处理
• 查找替换
${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹 配到的字符串,以substr替
换之 搜索替代,查找到内容并替换掉,不是贪婪模式,按顺序找到第一个不在往下寻找,最后面
也可以不加斜线。
${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹 配到的字符串,以substr替
换之 贪婪模式以两个“//”来表示,找到字符串中所有的root并替换掉。
${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹 配到的字符串,以substr替
换之 行首替代“#”来表示,只替换行首。
${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹 配到的字符串,以substr替
换之
行尾替换“%”表示,如果行尾内容不符也不继续往前寻找不做任何操作,内容符合则替换
掉。
• 字符串处理
• 查找并删除
${var/pattern}:删除var表示的字符串中第一次被pattern匹配到的字符串 删除字符串中第一个root。
${var//pattern}:删除var表示的字符串中所有被pattern匹配到的字符串 删除字符串中的所有root。(贪婪模式)
${var/#pattern}:删除var表示的字符串中所有以pattern为行首匹配到的 字符串 删除行首的root
${var/%pattern}:删除var所表示的字符串中所有以pattern为行尾所匹配 到的字符串
删除行尾的root但是行尾不是root所以不做操作,改为bash后则删除行尾bash。
• 字符大小写转换
${var^^}:把var中的所有小写字母转换为大写
${var,}:把var中的所有大写字母转换为小写
大小写字母转换示例:
小用法把string^^的值赋给STR
• 变量赋值写法(高级字符串赋值语句写法)
var=${str-expr} 实现三种情况的判断,var变量 str字符串 expr表达式 var的值由str来决定。
name没有配置
name为空字符串,和没有配置是有区别的,空串只是表示为空值不是没有配置。
(可以查看test帮助参考)
test -v +变量名查看 返回值为1则是没有配置返回值为0则是配置过的,哪怕是空
值。
name配置为非空字符串
var=${str:-expr} 和上面的唯一不同的是 空值有变化,如果配置为空则显示expr
示例:
总结:实现各种条件判断,根据name的值来影响title的值或赋值。
高级变量用法-有类型变量
• Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令 用于指定变量的类型,
两个命令是等价的
• declare [选项] 变量名
-r 声明或显示只读变量 (常量)
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母 declare –l var=UPPER
-u 声明变量为大写字母 declare –u var=lower
• eval命令
• eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令 适用于那些一次扫描无
法实现其功能的变量.该命令对变量进行两次扫描
• 第一步先把里面涉及到的命令先替换掉,在运行后面的命令。
• 示例:
直接执行第一条命令的话,会把{1…$n}当成字符串输出,加了eval之后将会首先扫描命令行进行所
有的置换,然后再执行该命令。
eval for的用法实现,及错误示例。
1、错误:当成字符串输出
2、错误:eval是命令需要用反引号引起来要不还是人为是字符串。
3、错误:eval 不具备输出功能,只是进行置换,所以还需要加echo来输出。
4、正确写法
• 间接变量引用
• 如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值 就称为间接变量引
用
• variable1的值是variable2,而variable2又是变量名,variable2的值为value, 间接变量引用是指通过
variable1获得变量值value的行为
variable1=variable2
variable2=value
echo $$ 显示为pid ,所以需要转义一下,最后加eval进行置换扫描两次。
• bash Shell提供了两种格式实现间接变量引用
eval tempvar=$
v
a
r
i
a
b
l
e
1
t
e
m
p
v
a
r
=
variable1 tempvar=
variable1tempvar={!variable1}
• 示例:
[root@server ~]# N=NAME
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1 wangxiaochun
[root@server ~]# eval N2=$$N
[root@server ~]# echo $N2 wangxiaochun
创建临时文件
mktemp命令:创建并显示临时文件,可避免冲突
mktemp [OPTION]… [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出现三个
把生成的文件名赋给file,作为feli的值。这样可以精确的查找生成随机的文件名。
OPTION:
-d 创建临时目录
-p DIR或–tmpdir=DIR 指明临时文件所存放目录位置
其实等价与 mktemp /data/test/fileXXX 写法
示例:
mktemp /tmp/testXXX
tmpdir=mktemp –d /tmp/testdirXXX
mktemp --tmpdir=/testdir testXXXXXX
总结:避免生成的临时文件名冲突。
写一个替换rm命令的别名脚本,删除文件的替代命令。
加上执行权限,在设置为rm别名。
也可以使用通配符*移动多个 ,但是显示效果显示为一个,可以做循环一个一个处理
。
安装复制文件
install命令: 功能相当于cp+chmod+chown+chgrp这些命令的组合,它拷贝文件并且设置权限甚至自
己建文件夹。
install [OPTION]… [-T] SOURCE DEST 单文件
install [OPTION]… SOURCE… DIRECTORY
install [OPTION]… -t DIRECTORY SOURCE…
install [OPTION]… -d DIRECTORY…创建空目录
选项:
-m MODE,默认755
-o OWNER
-g GROUP
示例:
install -m 700 -o wang -g admins srcfile desfile
拷贝到/data/test/目录下 ,修改其所有者、所属组、权限、文件名。
install –m 770 –d /testdir/installdir 建文件夹
• expect介绍
• expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主 要应用于自动化交互式操
作的场景,借助 expect 处理交互的命令,可以将交互过 程如:ssh登录,ftp登录等写在一个脚本
上,使之自动化完成。尤其适用于需要对 多台服务器执行相同操作的环境中,可以大大提高系统
管理人员的工作效率
人工交互式命令例:ssh、scp
ssh:需要手动输入yes/no,还有口令。
scp:需要输入口令。
程序代替人工:解决人工交互输入口令变为非交互式批量执行,expect实现。
expect centos6、7、8默认没有安装,先进行安装。
rpm -qi expect 查看包的信息和支持工具。下面解释有把哪些应用的人工交互式转换为非交互式方
式。
• expect命令 包含一个expect的子命令
• expect 语法:
expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
• 选项
○ -c:从命令行执行expect脚本,默认expect是交互地执行的 示例:expect -c 'expect “\n” {send “pressed enter\n”}
○ -d:可以输出输出调试信息 示例:expect -d ssh.exp
• expect中相关命令
○ spawn 启动新的进程 (用来监控软件程序)
○ expect 从进程接收字符串 (用来捕获关键字)
○ send 用于向进程发送字符串 (用来发送需要提交的东西)
○ interact 允许用户交互
○ exp_continue 匹配多个字符串在执行动作后加此命令
捕获关键字:包含也捕获。
scp:因为用的是expect所以用的shebang机制,不能用bash的shebang机制,不能用bash来执行和
检查要不然会报错。
作用:捕获yes/no关键字,一旦捕获到自动提交yes,捕获password关键字,捕获到自动提交口令,代
替人工输入yes和口令,需要加执行权限。
利用bash来完成。
ssh:代替人工登录,使用interact交互执行,还可以继续交互,不退出。
示例:expect 变量
使用变量来代替手动写ip,口令,防止下次更改麻烦。
示例:expect 位置参数
使用位置参数,来代替ip 、用户名、口令
示例:expect 执行多个命令,链接之后继续执行命令,在centos6中创建一个用户并设置密码。
示例:shell脚本调用expect
expect
• expect最常用的语法(tcl语言:模式-动作)
• 单一分支模式语法:
○ expect “hi” {send “You said hi\n"}
○ 匹配到hi后,会输出“you said hi”,并换行
• 多分支模式语法:
expect “hi” { send “You said hi\n” } \
“hehe” { send “Hehe yourself\n” }
“bye” { send “Good bye\n” }
• 匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:
expect {
“hi” { send “You said hi\n”}
“hehe” { send “Hehe yourself\n”}
“bye” { send " Good bye\n"}
}