一、退出状态
- 进程通过退出状态报告进程运行成功或失败
-
echo $?
查看上一条命令执行的退出状态 - 0代表运行成功,1-255代表运行失败
-
exit [n]
自定义退出状态码 - 如果未指定退出状态码,脚本运行结束后的退出状态码为执行脚本最后一条命令的退出状态码
- 实验:
(一)编写脚本error.sh,代码如下:
# /bin/bash
#
pwd
cmd
exit 100
执行结果如下:
由于没有cmd这条命令,所以脚本运行报错,退出状态码为指定的100。
(二)改动脚本error.sh,改动后的代码如下:
# /bin/bash
#
pwd
cmd
(exit 100)
echo hello
执行结果如下:
发现虽然设置了exit命令,但之后的命令仍然被执行。原因在于将exit命令放置在小括号中,小括号的意义为在当前进程中新增子进程,exit命令的作用变为退出error.sh进程创建的子进程,父进程仍旧正常运行。
二、算术运算
- 运算符号:+(加),-(减),*(乘),/(除),%(取余),**(乘方)
- 实现算数运算的方法
- let var=算术表达式
- var=$[算术表达式]
- var=$((算术表达式))
- var=$(expr arg1 arg2 arg3 ...)
- declare -i var=算术表达式
- echo 算术表达式 | bc
- let用法
- $[]和$(())用法
- expr用法
- declare -i用法
- 乘法*符号有时需要转义
- bash内建有随机数生成器$RANDOM,可以用于生成一定范围的随机数,如生成2-50的随机数$[$RANDOM%49+2]
- 增强型赋值:+=,-=,*=,/=,%=,例如a+=3等于a=a+3,其他符号类似
- 自增、自减:++,--,例如a++,b--
- 自增自减运算符在变量前后可能导致不同的结果,运算符在前如++a表示对变量a自增1再进行其他操作,运算符在后如b--表示对变量b先进行其他操作再自减1
三、逻辑运算
- 逻辑运算的结果只有true或false,但是不同情况下对true或false的数字描述不同
- 与运算:只有均为true,结果才为true,否则结果均为false
- 或运算:只有均为false,结果才为false,否则结果均为true
- 非运算:true取非结果为false,false取非结果为true
- 短路与 &&:第一个为0,第二个跳过计算,结果一定为0;
第一个为1,继续计算第二个,才能计算出结果 - 短路或 ||: 第一个为1,第二个跳过计算,结果一定为1;
第一个为0,继续计算第二个,才能计算出结果 - 异或^:相同为假,不同为真,异或可以用于交换两个值
四、条件测试
(一)测试命令
- test expression
- [ expression]
- [[ expression ]]
- 括号内的expression前后都需要有空格
- COMMAND1 && COMMAND2,COMMAND1为真时执行COMMAND2
- COMMAND1 || COMMAND2,COMMAND1为假时执行COMMAND2
- COMMAND1 && COMMAND2 || COMMAND3,可以实现当COMMAND1执行结果为真时,执行COMMAND2;当COMMAND1执行结果为假时,执行COMMAND3
(二)数值测试
-v VAR 变量VAR是否设置
-eq 是否等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
-ne 是否不等于
实验:实现当磁盘利用率超过80%时,自动报警
代码如下:
#! /bin/bash
#
diskusage=`df | grep "/dev/sd" | grep -o "[0-9]\{1,3\}%" | tr -d % | sort -nr | head -1`
[ "$diskusage" -ge 80 ] && echo "disk will be full"
- 执行结果如下:
(三)字符串测试
- == 是否等于
- > 是否大于
- < 是否小于
- != 是否不等于
- =~ pattern 是否匹配正则表达式,正则表达式为扩展正则表达式
- -z "string" 字符串是否为空,空为真,非空为假
- -n "string" 字符串是否非空,非空为真,空为假
- 字符串测试中的操作数都需要打引号,才能确保结果正确
- 可以看出变量var非空时为真,空时为假
- 变量abc为空,测试时使用-n选项应该非空为真,空为假,不会执行第二条命令打印true。但是当变量未有引号包含时,执行打印true,显然不对。变量有引号包含后,第二条命令不运行,符合预期。所以在字符串测试中一定要对变量打引号。
(四)文件测试
-
存在性测试
- -a 或-e 存在为真,不存在为假
-
类别测试
- -f 是否存在且为普通文件
- -d 是否存在且为目录文件
- -h 或 -L 是否存在且为符号链接文件
- -b 是否存在且为块设备文件
- -c 是否存在且为字符设备文件
- -p 是否存在且为管道文件
- -s 是否存在且为套接字文件
- 判断文件类型时,遇到软链接文件会直接判断链接的源文件类型,所以要先判断是否为软链接文件
- 实验:
-
文件权限测试
- -r 是否存在且可读
- -w 是否存在且可写
- -x 是否存在且可执行
-
文件特殊权限测试
- -u 是否存在且拥有suid权限
- -g 是否存在且拥有sgid权限
- -k 是否存在且拥有sticky权限
实验:判断文件后缀是否为.sh,若是则判断其是否具有可执行权限,若是则退出,否则为其增加可执行权限
- 文件大小测试
- -s 文件是否存在且非空
- 文件属性测试
- -O 文件上一次被读取后是否被修改过,即mtime是否新于atime
- -U 当前用户是否为文件属主
- -G 当前用户是否为文件属组
(五)双目测试
- file1 -ef file2 两个文件是否属于相同分区同一个inode号
- file1 -nt file2 file1是否新于file2,比较mtime
- file1 -ot file2 file1是否旧于file2,比较mtime
- 实验:验证两个文件是否同一个inode号
(六) 组合测试
- 第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
!COMMAND 非 - 第二种方式(只在组合测试命令时使用):
expression1 -a expression2 并且
expression1 -o expression2 或者
!expression 非
五、read 将输入分配给一个或多个变量
- -p 指定要显示的提示
- -s 静默输入,用于密码输入
- -n N 指定输入的字符长度N
- -d char 自定输入的结束符
- -t N timeout为N秒
- read从标准输入读入多个单词,每个单词一个变量,若变量个数少于单词数,则多出的单词也赋给最后一个变量
- 实验
六、bash展开命令行的顺序
- 把命令行分成单个命令词
- 展开别名
- 展开大括号的声明({})
- 展开波浪符声明(~)
- 命令替换($()和``)
- 再次把命令行分成命令词
- 展开文件通配(*、?、[abc]等等)
- 准备I/0重导向(<、>)
- 运行命令
七、bash的配置文件
- 全局配置文件
- /etc/profile
- /etc/profile.d/*.sh
- /etc/bashrc
- 个人配置文件
- ~/bash_profile
- ~/bashrc
- 交互式登录:终端输入账号密码登录或者
su - username
登录
配置文件执行顺序:/etc/profile -> /etc/profile.d/*.sh -> ~/bash_profile -> ~/bashrc -> /etc/bashrc - 非交互式登录:图形终端登录、
su username
登录、执行脚本
配置文件执行顺序:~/bashrc -> /etc/bashrc -> /etc/profile.d/*.sh - profile类文件配置功能
- 定义环境变量
- 运行脚本
- bashrc类文件配置功能
- 定义命令别名和函数
- 定义本地变量
- 配置文件生效
- 重启shell进程
-
.
或者source
八、bash的退出任务
- 退出任务保存在
~/bash_logout
文件中 - 在退出登录的shell时运行
~/bash_logout
文件 - 可用于退出后创建自动备份、清除临时文件等功能
九、$- 变量
- h:hashall,打开这个选项后,Shell会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选项关闭
- i:interactive-comments,包含这个选项说明当前的shell是一个交互式的shell。在脚本中,i选项是关闭的
- m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
- B:braceexpand,大括号扩展
- H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的一个历史命令,“!n”返回第n 个历史命令