Linux doc 2011 by: zollty
(如无特殊说明,本文所有的shell都是基于bash shell,而非dash sh)
有些linux的sh指向bash,两者等价,但有些则不一样。两者的区别参见:
https://www.cnblogs.com/macrored/p/11548347.html
https://www.jianshu.com/p/762d4cccee7e
布尔类型的定义和判断
the_world_is_flat=true # …do something interesting… if [ "$the_world_is_flat" = true ] ; then echo 'Be careful not to fall off!' fi
字符串按位数截取
语法:${string: start :length}
例如:
url="c.zollty.com" echo ${url: 2: 6} # 结果为zollty
字符串正则表达式替换、分割
替换格式:${string//old/new}
示例如下:
#!/bin/bash string="hello,shell,split,test" array=(${string//,/ }) for var in ${array[@]} do echo $var done
再举个例子:string="hello=shell",将 ‘=’ 替换成 ‘,’ 如下
${string/=/,}
读懂下面代码:
#!/bin/bash for i in `seq 1 10`; do node main.js && s=$? && break || s=$?; echo "Tried $i times. Waiting 5 secs...$?"; sleep 5; done;(exit $s)
知识点:$?
$?代表上一次命令的执行状态,成功则为0,失败则不为0(通常为1或2)
知识点:exit n (n=0,1,2...)
n=0 代表正常退出,否则不正常退出。
知识点:与和非(&&和||)
aa && bb:代表左边的命令aa执行成功后,才执行右边的命令bb
aa || bb:和&&相反,左边的aa执行失败后,才执行右边的bb
上面的例子为 aa && bb && cc || dd 格式,意思是:
(aa && bb && cc) || dd,aa 成功执行bb,bb成功执行cc,无论aa、bb、cc哪个失败,dd都会执行。
注意:不要用 aa || bb && cc,因为 aa失败了,bb会执行,然后cc也会执行;但如果aa成功了,bb不会执行,但是cc任然会执行。所以无论aa成功或失败,cc都会执行,这不是我们想要的。如果想aa成功时不执行cc,则应写成:
aa || (bb; cc)
见下面的说明:
知识点:shell 小括号、花括号
(aaa; bbb; ccc) 的意思是将多个命令作为一个整体执行,新开一个shell进程执行括号里面的脚本。
如果换成{aaa; bbb; ccc},就是在当前进程中执行。
两者的区别:(重要!!)
()只是对一串命令重新开一个子shell进行执行 {}对一串命令在当前shell执行 ()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开 ()最后一个命令可以不用分号 {}最后一个命令要用分号 {}的第一个命令和左括号之间必须要有一个空格 ()里的各命令不必和括号有空格 ()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令。
现学现用:我们想让npm install执行失败后,打印出log信息,然后再退出,怎么办?
答案:
npm install || s=$? if [ $s ]; then cat /root/.npm/_logs/*.log exit $s fi echo 'ok' 或者简写为 npm install || { s=$?; cat /root/.npm/_logs/*.log; exit $s} echo 'ok' 或者简写为 set -e npm install || (s=$?; cat /root/.npm/_logs/*.log; exit $s) echo 'ok'
注意后面那种写法,必须加上set -e,否则exit无法退出,后面的程序会继续执行。
不推荐最后那种写法。中间那种写法更合适,因为花括号是在当前进程中执行,exit会退出当前进程。而后面那种写法使用的小括号,是新开一个进程,这样如果不设置 set -e,当前进程就不会结束。
bash的管道( | )问题
/bin/sh -c wget -O - https://some.site | wc -l > /number
this only evaluates the exit code of the last operation in the pipe to determine success.
上例中只要 wc -l 命令成功,build就成功了,即使 wget 命令失败了。
If you want the command to fail due to an error at any stage in the pipe, 设置 set -o pipefail && to ensure that an unexpected error prevents the build from inadvertently succeeding. For example:
set -o pipefail && wget -O - https://some.site | wc -l > /number
注意:不是所有的 shells 都支持 -o pipefail 选项:比如 the dash shell on Debian-based images,
建议使用下面的格式来显式声明/bin/bash 设置 pipefail 选项:
/bin/bash -c set -o pipefail && wget -O - https://some.site | wc -l > /number
bash的set -e
set -e的意思是,根据每一个子命令的返回结果(exit状态码),来确定是否退出,如果状态码不为0,则退出整个进程。
注意,通常不这样设置,因为某个子命令的状态码不为0,不代表这个命令执行异常。例如diff命令
diff pom.xml pom.xml2
如果两个pom.xml不相同,则diff返回的状态码不为0,如果设置了 set -e,整个shell脚本就会退出。实际上diff不同是我们预料的结果,不应该退出shell进程。我曾经就被这个问题坑过!!
解决方案(重要实践经验!):设置set -e,同时在不希望exit非0退出的地方加上“||”,例如:
echo 'xxx' diff aa.sh bb.sh || { s=$?; echo 'aa and bb is diffrent'; exit $s; } echo 'yyyy'
获取参数
1、$n(n=1,2,3...) 代表获取第n个参数。
2、start.sh "$@" 将所有参数(空格分割)原封不动传给 start.sh
3、start.sh "${@:2}" 将第一个除外的所有参数(空格分割)原封不动传给 start.sh
Linux的$?特殊含义:
$$:Shell本身的PID(ProcessID,即脚本运行的当前 进程ID号)
$!:Shell最后运行的后台Process的PID(后台运行的最后一个进程的 进程ID号)
$?:最后运行的命令的结束代码(返回值)即执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
$-:显示shell使用的当前选项,与set命令功能相同
$*:所有参数列表。如"$*"用「...」括起来的情况,以"$1 $2 … $n"的形式输出所有参数,此选项参数可超过9个。
$@:所有参数列表。如"$@"用「...」括起来的情况,以"$1" "$2" … "$n" 的形式输出所有参数。跟$*类似,但是可以当作数组用
$#:添加到Shell的参数个数
$0:Shell本身的文件名
+ (点击以下标题显示正文内容)
if-判断
+ (点击以下标题显示正文内容)
在 Shell 脚本中调用另一个 Shell 脚本的三种方式
+ (点击以下标题显示正文内容)
awk的用法