使用 RETURN 陷阱

使用 RETURN 陷阱

我正在编写一个需要使用 执行的脚本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 指定的命令会在使用orRETURN执行的 shell 函数或 shell 脚本返回之后恢复执行之前执行。.source

https://www.gnu.org/software/bash/manual/bash.html

主脚本

#!/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 的回答涵盖了所有情况。

相关内容