set
Bash script command is an important part, but often overlooked, leading to the safety of the script and maintainability problems. This article describes its basic usage, so you can feel more comfortable using a Bash script.
I. Introduction
We know that when Bash script execution, it will create a new Shell.
$ bash script.sh
The above code, script.sh
is performed in which a new Shell. The Shell is the execution environment of the script, Bash default given the various parameters of the environment.
set
Command to change the operating parameters of the Shell environment, that is, you can customize the environment. There are more than a dozen parameters can be customized, the official manual has a complete list, this article describes the most common of four.
By the way, if without any command line parameters, run directly set
, it will show all the environmental variables and the Shell function.
$ set
Two, set -u
When executing the script, if you encounter a variable that does not exist, Bash default ignore it.
#!/usr/bin/env bash echo $a echo bar
The above code, $a
is a variable does not exist. Execution results are as follows.
$ bash script.sh bar
You can see, echo $a
the output of a blank line, Bash ignores that does not exist $a
, then continue echo bar
. In most cases, this is not the behavior of a developer wants encountered variable does not exist, the script should error, rather than silently down the execution.
set -u
It is used to change this behavior. Coupled with its head in the script, encounters a variable that does not exist would be an error, and stop the execution.
#!/usr/bin/env bash set -u echo $a echo bar
Results are as follows.
$ bash script.sh bash: script.sh:行4: a: 未绑定的变量
We can see, the script error, and no longer perform the statements that follow.
-u
There is another way -o nounset
, they are equivalent.
set -o nounset
Three, set -x
By default, the script is executed, the screen only displays the results of running, nothing else. If you execute multiple commands in a row, their operating results will be continuous output. Sometimes hard to tell, what a piece of content is generated by the command.
set -x
Before running for the result, the first output of the line command execution.
#!/usr/bin/env bash set -x echo bar
Implementation of the above script with the following results.
$ bash script.sh + echo bar bar
It can be seen perform echo bar
before, the command prints out the first line to +
represent. This is for debugging complex scripts are very useful.
-x
There is another way -o xtrace
.
set -o xtrace
Four, Bash error handling
If the script which has failed to run the command (return value of non-0), Bash default will continue to execute subsequent commands.
#!/usr/bin/env bash foo echo bar
The above script, foo
is a non-existent command will complain when executed. However, Bash will ignore this error and continue down the implementation.
$ bash script.sh script.sh:行3: foo: 未找到命令 bar
We can see, Bash just display an error, and not terminated.
This behavior is not conducive to safety and debug scripts. The actual development, if a command fails, it often requires a script to stop execution, to prevent accumulation of error. In this case, using the following general wording.
command || exit 1
The above wording that as long as command
there is a non-zero return value, the script will stop executing.
If a plurality of operations required to complete before the execution is stopped, it is necessary using three writing below.
# 写法一 command || { echo "command failed"; exit 1; } # 写法二 if ! command; then echo "command failed"; exit 1; fi # 写法三 command if [ "$?" -ne 0 ]; then echo "command failed"; exit 1; fi
In addition to stop the execution, there is a situation. If there are two commands inheritance, only the first command is successful, before proceeding to the second command, then we must use the following wording.
command1 && command2
Five, set -e
The above wording is somewhat cumbersome, easy to neglect. set -e
Solved this problem fundamentally, it makes the script as long as an error occurs, it is terminated.
#!/usr/bin/env bash set -e foo echo bar
Execution results are as follows.
$ bash script.sh script.sh:行4: foo: 未找到命令
You can see, the fourth row after execution fails, the script is terminated executed.
set -e
The return value to judge whether a command fails. However, some non-zero return value of the command may not indicate failure, or in the case of developers want to command fails, the script continue execution. Then you can temporarily turn off set -e
after the end of the command execution, and then re-open set -e
.
set +e command1 command2 set -e
The above code, set +e
means closed -e
option set -e
represents reopen -e
option.
Another method is to use command || true
so that even if the command execution fails, the script will not be terminated.
#!/bin/bash set -e foo || true echo bar
The above code, true
making this line statement is always executed successfully, the latter echo bar
will be executed.
-e
There is another way -o errexit
.
set -o errexit
Six, set -o pipefail
set -e
There is one exception, that is not suitable for pipeline command.
The so-called Pipe command is a plurality of sub-commands pipeline operator ( |
) combined into one big order. Bash will return a value of the last sub-command, the entire command as the return value. In other words, as long as the last sub-command does not fail, the pipeline will always command is successful, it will still be behind the command execution, set -e
it becomes ineffective.
Consider the following example.
#!/usr/bin/env bash set -e foo | echo a echo bar
Execution results are as follows.
$ bash script.sh a script.sh:行4: foo: 未找到命令 bar
The above code, foo
is a non-existent command, but foo | echo a
this command is executed successfully pipeline, causing the latter echo bar
will continue.
set -o pipefail
To resolve this situation, as long as a sub-command fails, the entire pipeline command fails, the script will be terminated.
#!/usr/bin/env bash set -eo pipefail foo | echo a echo bar
After running the following results.
$ bash script.sh a script.sh:行4: foo: 未找到命令
We can see, echo bar
there is no execution.
Seven summary
set
These four parameters above command, are generally used together.
# 写法一 set -euxo pipefail # 写法二 set -eux set -o pipefail
Both written recommendations on the head all Bash scripts.
Another option would be in the implementation Bash script, passing the command line parameters.
$ bash -euxo pipefail script.sh