我正在编写一个需要使用 执行的脚本source
,因为它的任务是修改环境。在脚本执行过程中,我想使用 ,set -e
以便任何错误都会停止脚本。该脚本如下所示:
#!/bin/bash
set -e
# do something
cd somewhere
source anotherScript
问题是set -e
脚本完成后,它自然仍然有效。如何确保set
脚本停止时(以任何方式 - 无论是成功完成还是出现错误)更改的选项正确恢复到其先前的值?
答案1
与激活它的方式完全相同:调用 buitin set
:
$ set -o errexit
$ set -o | grep errexit
errexit on
$ set +o errexit
$ set -o | grep errexit
errexit off
在手册页的“set”命令部分bash(1)
下:SHELL BUILTIN COMMANDS
-o option-name
The option-name can be one of the following:
errexit Same as -e.
答案2
该命令set +o
将当前设置列为恢复相同状态的命令,例如
$ set +o
set +o allexport
set -o braceexpand
set -o emacs
set +o errexit
set +o errtrace
...
如果将此输出保存到 shell 变量,则可以稍后轻松恢复所有选项:
SAVED_OPTIONS=$(set +o)
set -e
# do something
eval "$SAVED_OPTIONS"
Bash 还包含许多非标准(非 POSIX)选项,这些选项可使用shopt
命令进行调整。可以使用命令shopt -p
以类似的方式保存这些选项。
如果只想保存和恢复一个选项,可以使用 $- 环境变量,该变量以字母形式列出当前的选项集,例如
$ echo $-
himBH
您可以使用类似这样的方法来保存和恢复特定选项:
[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
答案3
使用 RETURN 陷阱
RETURN
陷阱也适用于源脚本。
使用 trap 指定的命令会在使用or
RETURN
执行的 shell 函数或 shell 脚本返回之后恢复执行之前执行。.
source
主脚本
#!/usr/bin/env bash
echo "inside main script"
shopt -o errexit
source a_script_to_be_sourced.sh
echo "back inside main script"
shopt -o errexit
待获取脚本.sh
trap "$(shopt -p -o errexit)" RETURN
set -e # Equivalents: set -o errexit; shopt -s -o errexit
echo "inside sourced script"
shopt -o errexit
测试
$ ./main_script.sh
inside main script
errexit off
inside sourced script
errexit on
back inside main script
errexit off
答案4
恢复之前活性可以快速完成设置:
PREV_SETTING=$- # e.g. himxBH (there was xtrace)
set +x
# do your script without xtrace, ...
set -$PREV_SETTING
反过来(恢复到关闭状态)据我所知没有这样的捷径,并且 Seppo 的回答涵盖了所有情况。