使用“源”运行脚本时如何正确还原设置?


9

我正在编写一个脚本,该脚本需要使用来执行source,因为它的任务是修改环境。在脚本执行过程中,我要使用脚本,set -e以便任何错误都可以停止脚本。该脚本如下所示:

#!/bin/bash
set -e
# do something
cd somewhere
source anotherScript

问题在于set -e脚本完成后自然仍然有效。set在脚本停止时(以任何方式-通过成功完成或发生错误),如何确保更改后的选项正确恢复到其上一个值?



抑制回显命令的执行跟踪是否解决了相同的问题(针对-x/ xtrace选项)
斯科特,

Answers:


3

激活方式完全相同:调用buitin set

$ set -o errexit
$ set -o | grep errexit
errexit         on
$ set +o errexit
$ set -o | grep errexit
errexit         off

bash(1)联机帮助页的SHELL BUILTIN COMMANDS“ set”命令下:

-o option-name
The option-name can be one of the following:
    errexit Same as -e.

3
有没有办法保存(所有)这些设置并在以后还原它们?
PetrPudlák13年

运行set -o以了解您当前的设置。在脚本上设置/取消设置它们时,要明确。
dawud

12

该命令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还包括许多使用shopt命令调整的非标准(非POSIX)选项。该命令shopt -p可用于以类似方式保存这些选项。

如果只想保存和恢复一个选项,则可以使用$-环境变量,该变量以字母形式列出当前的选项集,例如

$ echo $-
himBH

您可以使用以下方式来保存和恢复特定选项:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e

请注意,不要错过eval调用中“ $ SAVED_OPTIONS”周围的引号,这一点非常重要。
马特

3

使用返回陷阱

RETURN 陷阱也适用于源脚本。

RETURN在使用.source返回执行的shell函数或shell脚本之后,将在执行恢复执行之前执行由陷阱指定的命令。

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

main_script.sh

#!/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

a_script_to_be_sourced.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

2

恢复先前激活的设置可以快速完成:

PREV_SETTING=$-  # e.g. himxBH  (there was xtrace)

set +x
# do your script without xtrace, ...

set -$PREV_SETTING

反之(恢复到关闭状态)AFAIK没有这样的快捷方式,Seppo的答案涵盖了所有情况。


您的代码以书面形式产生,-bash: set: -i: invalid option是因为该-i标志说明了一个交互式外壳。
dpw
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.