如果仅仅是一个set,不加任何参数,就是显示所有的环境变量,但是我的Ubuntu系统,不仅显示环境变量还会显示函数。
set后面的每个值都会传递到位置参数*positional parameter *里,如以下例子:
hope@hope:~$ set ONE TWO THREE
hope@hope:~$ echo $1
ONE
hope@hope:~$ echo $2
TWO
hope@hope:~$ echo $3
THREE
hope@hope:~$
ONE传给了$1, 以此类推。
使用set --可以清除所有位置参数,如下例:
hope@hope:~$ echo $*
ONE TWO THREE
hope@hope:~$ set --
hope@hope:~$ echo $*
hope@hope:~$
Linux Shell脚本对于未定义变量,直接使用是输出空行,这样就容易被忽略,比如我写了一个简单的脚本,是输出变量FOO的值,但是变量不存在的,先看看运行什么效果:
hope@hope:~$ cat script.sh
#!/bin/bash
echo $FOO
hope@hope:~$ ./script.sh
hope@hope:~$
意料之中,输出一个空行。在脚本里加上set -u会让不存在的变量报错,我们实验一下。
hope@hope:~$ cat script.sh
#!/bin/bash
set -u
echo $FOO
hope@hope:~$ ./script.sh
./script.sh: line 3: FOO: unbound variable
hope@hope:~$
上面的例子是不存在的变量,但是实际情况还有不存在的命令。对于不存在的命令,也可以做个实验,结果如下:
hope@hope:~$ cat cnf-script.sh
#!/bin/bash
foo
echo "hello, world"
hope@hope:~$ ./cnf-script.sh
./cnf-script.sh: line 3: foo: command not found
hello, world
hope@hope:~$
虽然遇到了不存在的命令,但是脚本还是继续执行了,我们希望遇到错误就停止脚本。那么可以这样改写脚本,再执行:
hope@hope:~$ vi cnf-script.sh
hope@hope:~$ cat cnf-script.sh
#!/bin/bash
set -e
foo
echo "hello, world"
hope@hope:~$ ./cnf-script.sh
./cnf-script.sh: line 5: foo: command not found
这样遇到错误后脚本就不再往下执行了。
但是set -x对管道就没作用了啊。我举个例子:
hope@hope:~$ vi pipe-script.sh
hope@hope:~$ cat pipe-script.sh
#!/bin/bash
set -e
foobar | echo "Hello"
echo "Today is Sep 21,2020."
hope@hope:~$ chmod +x pipe-script.sh
hope@hope:~$ ./pipe-script.sh
Hello
./pipe-script.sh: line 3: foobar: command not found
Today is Sep 21,2020.
set -e没有取任何作用,没有阻止后面句子的打印,怎么办呢?这时候需要改写了,使用set -eo pipefail代替吧,虽然管道后面的命令还是会执行,但之后的命令就不会执行了,如下例:
hope@hope:~$ cp pipe-script.sh pipefail-script.sh
hope@hope:~$ vi pipefail-script.sh
hope@hope:~$ cat pipefail-script.sh
#!/bin/bash
set -eo pipefail
foobar | echo "Hello"
echo "Today is Sep 21,2020."
hope@hope:~$ ./pipefail-script.sh
Hello
./pipefail-script.sh: line 3: foobar: command not found
有时候我们需要知道执行的命令到底是什么,而不仅仅满足于显示命令执行结果,这个时候可以使用set -x来实现了以下是一个例子:
hope@hope:~$ vi setx-script.sh
hope@hope:~$ chmod +x setx-script.sh
hope@hope:~$ cat setx-script.sh
#!/bin/bash
set -x
echo "Hello, world!"
hope@hope:~$ ./setx-script.sh
+ echo 'Hello, world!'
Hello, world!