Bash 脚本执行
脚本执行
#!
脚本首行注释
- 文件执行时,shell会将文件内容发送至
#!之后的解释器上 - 不限于shell脚本,也适合其他类型的脚本语言
- 当然要求
#为脚本语言支持的注释符
- 当然要求
- 建议在首行使用
env命令而不是硬编码解释器路径,这样可以 减少对机器的依赖1
2!/usr/bin/env python
!/usr/bin/env shell
4种执行方式
$ file_name:表示在当前shell执行文件,需要有文件的执行 权限$ source/. file_name:source和.意义一致,表示读取 文件内容在shell中,然后在shell里执行文件内容,需要读权限$ sh file_name:表示开启一个新的shell进程,并读取文件 内容在新的shell中然后执行,同样的需读权限
例
以下面的文件test.sh为例
1 | !/bin/bash |
$ test.sh:产生两个新进程test.sh和sleep,在second输出 之前<ctrl-c>,会同时终止两个进程,不会继续输出second$ sh test.sh:产生两个新进程,shell和sleep,在second 输出之前<ctrl-c>,同样的会同时终止两个进程,不会继续 输出second(实际上first是在新的shell里输出的)source/. test.sh:产生一个新进程sleep,在second输出之前<ctrl-c>,只有sleep进程被终止,而test.sh的内容在当前 shell里直接执行,当前shell没有被终止,second会继续输出
结论
如果需要对当前shell进行设置,应该使用source/.
否则这三种执行方式除了进程产生、权限要求应该没有差别
Shell环境
环境变量
设置环境变量直接:
$ ENV_NAME=value(=前后不能有空格) 但是此时环境变量只能在当前shell中使用,需要export命令 导出之后才可在子shell中使用环境变量设置代理
1
2export http_proxy=socks://ip
export https_proxy=socks5://ip
输入输出
0:STDIN_FILENO,标准输入1:STDOUT_FILENO,标准输出2:STDERR_FILENO,标准错误
说明:
- 标准输出和标准错误虽然都是在命令行上显示,但是两个是
不同的流。输出重定向
>只能将标准输出重定向,不会将 标准错误重定向,其仍然会在命令行显示
重定向
<:重定向标准输入>:标准输出write重定向>>:标准输出add重定向2>:标准错误重定向
说明:
输出重定向就是
1 > output,command > output只是省略1的简写- 命名自己不是输出,不能重定向
- 是命令产生的标准输出重定向
可以通过
2>&1将标准错误重定向到标准输出,从而将命令的 标准输出、错误输出同时输出&这里表示等效于标准输出(标准输出的引用)command>a 2>a和command>a 2>&1看起来类似,实际上 前者写法会打开两次a,stderr覆盖stdout,而后者是 引用,不会覆盖、IO效率更高2>&1放在后面大概是因为需要获取stdout的引用,所以 需要标准输出先给出重定向- 这种写法还有个简写
&>、>&
可以重定向到设备,在*nix系统中,设备也被视为文件
1
echo "hello" > /dev/tty01
特别的设备
/dev/null可以作为不需要输出的重定向目标
HereDoc Format
HereDoc Format:特殊的重定向,指示shell从标准输入读取输入 直至遇到标记行(前后不能有空白符)
1 | <CMD> << <EOF> |
EOF:标记字符串,常用EOF、STOP等
若标记中含有字符被quote(如被引号包括)
- 结束标记为去除quotation结果
here-doc中不执行参数扩展、命令替换、算数扩展
若标记中没有quotation
here-doc中执行参数扩展、命令替换、算数扩展- 此时
\、$、反引号需要\转义
管道
|:将一个程序的标准输出发送到另一个程序的标准输入
- 一些平台会并行启动以管道连接的程序,此时使用类似迭代器 输出、输入能提高效率
Shell内置命令
which命令无法找到的命令
set
set:设置所使用的shell选项、列出shell变量
:不带参数,显示全部shell变量-a:输出之后所有至export(环境变量)-b:使被终止后台程序立即汇报执行状态-B:执行括号扩展-C:重定向所产生的文件无法覆盖已存在文件-d:shell默认使用hash表记忆已使用过的命令以加速 执行,此设置取消该行为-e:若指令回传值不为0,立即退出shell-f:取消使用通配符-h:寻找命令时记录其位置???-H:(默认)允许使用!加<编号>方式执行history中 记录的命令-k:命令后的=也被视为设置命令的环境变量-m:监视器模式,启动任务控制- 后台进程已单独进程组运行
- 每次完成任务时显示包含退出的状态行
-n:读取命令但不执行- 通常用于检查脚本句法错误
-p:允许set-user/group-id- 禁止处理
$ENV文件、从文件中继承shell函数
- 禁止处理
-P:处理cd等改变当前目录的命令时,不解析符号链接-t:读取、执行下条命令后退出-u:使用未设置变量作为错误处理-v:输入行被读取时,显示shell输出行-x:显示简单命令的PS4扩展值(包括所有参数)、当前命令 的环境变量-o:option-name,下列之一allexport:同-abraceexpand shell:(默认)执行花括号扩展emacs:(默认)使用emacs风格命令行编辑接口errexit:同-eerrtrace:同-Efunctrace:同-Thashall:同-hhistexpand:同-Hhistory:记录命令历史ignoreeof:读取EOF时不退出shellinteractive-comments:允许交互式命令中出现注释keyword:同-kmonitor:同-mnoclobber:同-Cnoexec:同-nnoglob:同-fnoglob:currently accepted but ignorednohash:同-dnotify:同-bnounset:同-uphysical:同-Ppipfail:管道命令返回值为最后返回值非0命令的状态, 若没有非0返回值返回0posix:改变shell属性以匹配标准,默认操作不同于 POSIX1003.2标准priviledged:同-pverbose:同-vvi:使用vi风格的命令编辑接口xtrace:同-x
+:加以上参数取消标志位设置(包括o参数)--:给所有剩余参数设置标志位,没有剩余参数则unset-:给所有剩余参数设置标志位
$-中存放有当前已设置标志位
let
let:执行计算的工具,用于执行一个、多个表达式
- 变量计算中不需要
$标识变量 - 表达式中包含特殊字符,需要引起来
declare
declare:声明变量内容
-a:声明变量为普通数组-A:声明变量为关联数组(下标支持字符串,类似字典)-i:声明变量为整形-r:声明变量只读-x:设置为环境变量(export)-g:在函数中创建全局变量+:和以上联合使用,取消定义的变量类型-f:列出脚本中定义的函数名称、函数体-F:列出脚本中定义的函数名称-p:查看变量属性、值
read
read:从标准输入读入变量内容
1 | read [<option>] <var>[ <var2>...] |
- 读取值数目大于变量数目时,多余值均赋给最后变量
-p:命令行提示内容-n:不换行-d:分隔标记-t:阻塞等待时常,之后返回非零-s:隐藏输入-r:反折号不被视为转义标记
1 | cat README | while read -r line; do |
shift
shift:移除参数列表中头部部分参数,缺省移除1个
shift移除从$1开始,无法移除$0
getopts
getopts:逐个读取解析单字符指示的参数
1 | function func (){ |
$OPTARG:参数值$OPTIND:在参数列表中位移,初始值为1,常配合shift使用剔除已处理参数- 遇到未指定option则返回0
option字符后
::字符可以带有参数,赋给$OPTARG;否则 仅表示标志,仅该字符被处理option_string开头
:可以避免错误输出:标记option不带参数时- 待匹配值设为
: $OPTARG设为option
- 待匹配值设为
- option无效时
- 待匹配值设为
? $OPTARG设为option
- 待匹配值设为
- 函数内部处理函数参数,否则处理脚本参数
- 参数标识
-可省略