bash shell
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bash shell相关的知识,希望对你有一定的参考价值。
编程基础
程序:指令+数据
程序编程风格:
过程式:以指令为中心,数据服务于指令
对象式:以数据为中心,指令服务于数据
shell程序:提供了编程能力,解释执行
程序的执行方式
计算机:运行二进制指令
编程语言:
低级:汇编
高级:
编译:高级语言-->编译器-->目标代码 java,C#
解释:高级语言-->解释器-->机器代码 shell, perl, python
编程逻辑处理方式:
- 顺序执行
- 循环执行
- 选择执行
shell 脚本的组成
对于shell脚本来是,它是一种弱类型,过程式的语言。不包括浮点型。
> 强类型:一个变量给他确定一个类型,赋值后,这个类型不可改变。
弱类型一个变量你不用给它指定类型,拿来就用。以至于拿到一个变量,你不知道它是个什么类型,默认是字符型。参与运算会自动进行隐式类型转换,变量无需事先定义可以直接调用。
shell脚本的用途有:
- 自动化常用命令
- 执行系统管理和故障排除
- 创建简单的应用程序
- 处理文本或文件
shell脚本: 包含一些命令或声明,并符合一定格式的文本文件
第一步:使用文本编辑器来创建文本文件
格式要求:首行shebang机制
-
- #!/bin/bash
- #!/usr/bin/python
- #!/usr/bin/perl
- 添加注释
- 注释以#开头
- 各种命令的组合
第二步:运行脚本
给予执行权限,在命令行上指定脚本的绝对或相对路径
直接运行解释器,将脚本作为解释器程序的参数运行
脚本规范
脚本代码开头约定
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后的时间
5、作者相关信息
6、该程序的作用,及注意事项
7、最后是各版本的更新简要说明
我们知道,一台Linux主机开机运行时,系统启动什么样的shell时,是由用户的个ID配置决定。也就是在/etc/passwd文件中个人用户的第7个字段决定。
我们目前所启用远程连接的伪终端还是物理机上开的虚拟终端开启的默认 shell为父shell。而在系统中输入bash或/bin/bash 会开启一个子shell
bash变量种类
本地变量
变量赋值:name="value"
- 可以直接是字符串:name="username"
- 变量引用:name="$PATH"
- 命令引用:name=`cmd` name=$(cmd)
变量引用中的强引用与弱引用
“”:弱引用,变量引用会被替换为变量值
‘‘:强引用,变量引用不会被替换,而保持原字符串。
注意
- 变量赋值时,变量建议加双引号。变量赋值用等号, 前后不带空格
- 变量里存放多行时,变量要用双引号才能保留原来的格式
- 当变量覆值含有空格的时候,变量的值要用双引号来界定字符的首尾。若不加引号,系统会以为空格后的字符是你输的命令。赋值时等号前后不能带有空格。
- 引用变量时是否要加$,
echo默认显示的是字符串,变量不加$,echo会把他当字符串,
能识别变量的命令可以不用加$。 - $naem与${name}本质相同,但出现十个以上的参数要加大括号,建议加上大括号。
变量要存一个新值,会存在一个新的内存中,以前的值所存放的空间会被系统回收,给别的应用程序来用。 - 虽然echo显示字符串可以不加双引号。但在脚本里要显示自己的文本消息时,如:echo Let‘s see if this‘ll work,这串文本消息中有自己的单引号,必须要用双引号给引起来。如果文本消息内有双引号出现,要加上“转义字符” \ 为了稳妥起见双引号比较好。
shell脚本里定义的变量在脚本的整个生命周期里有效,但在shell脚本结束时会被删除掉。
变量命名法则:
- 不能使程序中的保留字:例如if, for
- 只能使用数字、字母及下划线,且不能以数字开头
- 见名知义
- 统一命名规则:驼峰命名法
局部变量
- 局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
- 只在当前shell有效。
- 在下级的子进程定义的变量不会影响上一级进程。
环境变量
-
环境(全局)变量:生效范围为当前shell进程及其子进程
子进程可以用父进程的定义的变量也可以对变量进行更改,改完之后不能传给上级进程,但可以传给下级进程。 - 如果子进程把父进程定义的变量用unset给删了,父进程不受影响,只会影响到下一级子进程中。
位置变量
- 位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
-
$1, $2, ...:对应第1、第2等参数,shift [n]换位置
shift的用法:无法判断用户会输入几个参数,有两种方法来判断
1、先获取参数的个数。再来处理。
2、不管参数有多少,用shift,把参数住左移,默认是移一位,移多少位,在后面加个数字。 - $0: 命令本身======会写上全路径,可以用basename取基名
如果用的是软链接,$0会显示软链接的路径。 - $*: 传递给脚本的所有参数,全部参数合为一个字符串
- [email protected]: 传递给脚本的所有参数,每个参数为独立字符串
- $#: 传递给脚本的参数的个数
[email protected] $* 只在被双引号包起来的时候才会有差异 - set -- 清空所有位置变量
脚本调试
- 检测脚本中的语法错误
bash -n /path/to/some_script - 调试执行
bash -x /path/to/some_script
查看变量与进程号
- $$:一个进程的进程编号
- $PPID:代表的是父进程的进程编号
- pstree -p:查看进程与进程之间的关系
- export :可以声明一个变量为环境变量。
先声明后赋值,先赋值后来声明,都是可以的。 - export:显示的是系统中目前的环境变量。
- declare -x:也可以声明环境变量。
- env:显示所有的环境变量
- printenv :显示所有的环境变量
set 显示已定义的所有变量
销毁变量:unset name
变量使用完毕以后,用unset将变量删掉。在程序运行期间,变量不会在内存中释放空间的。日积月累,会被占用内存的空间。
bash内建的环境变量:
- PATH
- SHELL
- USER
- UID
- HOME
- PWD
- SHLVL
- LANG
- HOSTNAME
- HISTSIZE
- —
只读变量:只能声明,但不能修改和删除
声明只读变量:
- readonly name
- declare -r name
查看只读变量: - readonly –p
- declare -r
只读变量只能使用,不能修改,也不能删。常量的生命有效期是当前进程的有效期。
小括号与大括号的用
加上小括号相当于开了子进程,执行完又退回到父进程。可以认为是一次性任务,不影响当前进程
大括号不开启shell,会影响当前环境。
它们的相同点是:把括号里的命令做为一个整体,统一执行。
- { cmd; }
- (cmd)
示例[[email protected] bin]#x=1;echo "pid=$$";(echo "subpid=$$";echo "subx=$x";x=2;echo "subx2=$x");echo x=$x pid=3201 subpid=3201 subx=1 subx2=2 x=1
小括号的特性:这种开启子shell可继承父进程的变量和进程编号。
[[email protected] ~]#false || (echo cmd1;exit) cmd1 [[email protected] ~]#false || { echo cmd1;exit; } cmd1 logout
写脚本时用小括号 是退不出脚本的。
退出脚本
退出状态
进程使用退出状态来报告成功或失败
- 0 代表成功,1-255代表失败
- $? 变量保存最近的命令退出状态。
例如:
ping -c1 -W1 hostdown &> /dev/null
echo $?
退出状态码
- bash自定义退出状态码
exit [n]:自定义退出状态码
注意: - 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
- 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
- 当脚本里,有命令错误时,执行脚本还是会执行 下面的命令。
- 如果是语法错误,就不会向下执行命令了。
算术运算
- bash中的算术运算:help let
+, -, *, /, %取模(取余), **(乘方) - 实现算术运算:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...) 用乘法要用转义才行。
(5) declare –i var = 数值
把变量声明成数值
(6) echo ‘算术表达式’ | bc
?乘法符号有些场景中需要转义,如*
?bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之间随机数
赋值
- 增强型赋值:
+=, -=, *=, /=, %= - let varOPERvalue
例如:let count+=3
自加3后自赋值 - 自增,自减:
let var+=1
let var++
let var-=1
let var--
###逻辑运算
- true, false
1, 0 - 与:
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0 - 或:
1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0 - 非:!
! 1 = 0
! 0 = 1 - 短路运算
短路与
第一个为0,结果必定为0
第一个为1,第二个必须要参与运算
短路或
第一个为1,结果必定为1
第一个为0,第二个必须要参与运算 - 异或:^
异或的两个值,相同为假,不同为真
异或:
相同为假flase
不同为真true
[[email protected] ~]#a=4
[[email protected] ~]#b=6
[[email protected] ~]#echo $a $b
4 6
[[email protected] ~]#a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
6 4
[[email protected] bin]#false || echo cmd1 && echo cmd2
cmd1
cmd2
[[email protected] bin]#true || echo cmd1 && echo cmd2
cmd2
[[email protected] bin]#true || (echo cmd1;echo cmd2)
[[email protected] bin]#false || (echo cmd1;echo cmd2)
cmd1
cmd2
条件测试
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
?评估布尔声明,以便用在条件性执行中
?若真,则返回0
?若假,则返回1
?测试命令:
?test EXPRESSION
?[ EXPRESSION ]
?[[ EXPRESSION ]]
注意:EXPRESSION前后必须有空白字符
- -z 测试字符串是否为空,空为真,非空为假。
- -n 测试字符串是否为非空。非空为真,空为假。-n可以省略。
?根据退出状态而定,命令可以有条件地运行
?&& 代表条件性的AND THEN
?|| 代表条件性的OR ELSE
bash的字符串测试
- 字符串测试:
- == 是否等于
- \> ascii码是否大于ascii码
- \< 是否小于
- != 是否不等于
- =~ 左侧字符串是否能够被右侧的PATTERN所匹配
- 注意: 此表达式一般用于[[ ]]中;扩展的正则表达式
- -z "STRING“ 字符串是否为空,空为真,不空为假
- -n "STRING" 字符串是否不空,不空为真,空为假
注意:用于字符串比较时的用到的操作数都应该使用引号用到时正则表达式用两个中括号 ,test与一个中括号 是等价的。
bash的数值测试
- 数值测试:
-v VAR
变量VAR是否设置-v VAR被赋过值 和也算有值和空字符串是两码事
数值测试: - -gt 是否大于
- -ge 是否大于等于
- -eq 是否等于
- -ne 是否不等于
- -lt 是否小于
- -le 是否小于等于
注意
变量在中括号里写时要加双引号
当判断软链接时,判断的是软链接指向的文件。
判断权限判断的是实际权限
以上是关于bash shell的主要内容,如果未能解决你的问题,请参考以下文章