编写安全健壮的shell脚本
编写 shell 脚本容易出现的问题:比如变量为空的时候,管道报错等,容易引起一系列问题甚至灾难性的结果。
可以借助工具https://www.shellcheck.net/来检查脚本里面可以改进的地方。
脚本里使用 set
建议使用
1 | set -euo pipefail |
set -o
set -o
可以查看 shell 的选项开关,比如常用的 pipefail
1 | set -o | pipefail |
pipefail 是指在一个管道命令中,任意一个命令执行失败就认为命令报错(但是可以继续执行,想让它报错退出需要再加上 set -e)
可以在 shell 脚本开头加上 set -o pipefail
,我们来看一个例子:
1 |
|
set -e
set -e 是指任意一条命令返回值不是 0,脚本就退出不继续执行了。
如果有些程序想要人为的忽略报错,可以在命令开始前加上 set +e,命令结束的时候再 set -e,如:
1 |
|
set -u
将未设置的参数或者变量视为错误并退出脚本。
1 |
|
这个时候只会执行 echo 111,因为 ${123}不存在,脚本就报错退出了。
set -x
调试模式,会把每一个 shell 命令执行的结果都打印出来,效果等同于 bash -x test.sh
set -f
禁用文件名通配符,比如脚本
1 |
|
这个时候只会删除文件名为 *.md
的文件,并不会把所有.md 的文件都删除。
编写脚本注意事项
错误示范 | 正确示范 |
---|---|
a=`pwd` | a=$(pwd) |
echo $a | echo “${a}” |
trap 捕获错误
trap 是捕获信号的命令,常用的信号有:
编号 | 信号名称 | 缺省动作 | 描述 |
---|---|---|---|
1 | SIGHUP | 终止 | 终止进程,挂起 |
2 | SIGINT | 终止 | 键盘输入中断命令,一般是 CTRL+C |
3 | SIGQUIT | CoreDump | 键盘输入退出命令,一般是 CTRL+\ |
4 | SIGILL | CoreDump | 非法指令 |
5 | SIGTRAP | CoreDump | trap 指令发出,一般调试用 |
6 | SIGABRT | CoreDump | abort(3) 发出的终止信号 |
7 | SIGBUS | CoreDump | 非法地址 |
8 | SIGFPE | CoreDump | 浮点数异常 |
9 | SIGKILL | 终止 | 立即停止进程,不能捕获,不能忽略 |
10 | SIGUSR1 | 终止 | 用户自定义信号 1,像 Nginx 就支持 USR1 信号,用于重载配置,重新打开日志 |
11 | SIGSEGV | CoreDump | 无效内存引用 |
12 | SIGUSR2 | 终止 | 用户自定义信号 2 |
13 | SIGPIPE | 终止 | 管道不能访问 |
14 | SIGALRM | 终止 | 时钟信号,alrm(2) 发出的终止信号 |
15 | SIGTERM | 终止 | 终止信号,进程会先关闭正在运行的任务或打开的文件再终止,有时间进程在有运行的任务而忽略此信号。不能捕捉 |
16 | SIGSTKFLT | 终止 | 处理器栈错误 |
17 | SIGCHLD | 可忽略 | 子进程结束时,父进程收到的信号 |
18 | SIGCONT | 可忽略 | 让终止的进程继续执行 |
19 | SIGSTOP | 停止 | 停止进程,不能忽略,不能捕获 |
20 | SIGSTP | 停止 | 停止进程,一般是 CTRL+Z |
21 | SIGTTIN | 停止 | 后台进程从终端读数据 |
22 | SIGTTOU | 停止 | 后台进程从终端写数据 |
23 | SIGURG | 可忽略 | 紧急数组是否到达 socket |
24 | SIGXCPU | CoreDump | 超出 CPU 占用资源限制 |
25 | SIGXFSZ | CoreDump | 超出文件大小资源限制 |
26 | SIGVTALRM | 终止 | 虚拟时钟信号,类似于 SIGALRM,但计算的是进程占用的时间 |
27 | SIGPROF | 终止 | 类似与 SIGALRM,但计算的是进程占用 CPU 的时间 |
28 | SIGWINCH | 可忽略 | 窗口大小改变发出的信号 |
29 | SIGIO | 终止 | 文件描述符准备就绪,可以输入/输出操作了 |
30 | SIGPWR | 终止 | 电源失败 |
31 | SIGSYS | CoreDump | 非法系统调用 |
程序退出后删除临时文件
有时候我们的脚本会生成一些临时文件,虽然可以在脚本最后删除这些临时文件,但是有些例外情况比如脚本报错,这样临时文件就不能及时地清理掉,这个时候我们可以利用 trap 捕获 EXIT 信号来执行我们想要的命令。
1 |
|
程序意外退出删除临时文件
1 |
|
生成临时文件
可以使用 mktemp 命令生成 tmp 文件,mktemp -d 生成临时目录,避免临时目录重复使用的问题
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 杂烩饭!
评论