Jak poprawnie przywrócić ustawienia podczas uruchamiania skryptu przy użyciu „źródła”?

9

Piszę skrypt, który należy wykonać source, ponieważ jego zadaniem jest modyfikacja środowiska. Podczas skryptu chcę go używać set -e, aby każdy błąd zatrzymał skrypt. Skrypt wygląda następująco:

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

Problem polega na tym, że set -enaturalnie obowiązuje po zakończeniu skryptu. Jak mogę się upewnić, że zmieniona setopcja jest prawidłowo przywracana do wartości poprzedniej po zatrzymaniu skryptu (w jakikolwiek sposób - poprzez pomyślne ukończenie lub błąd)?

Petr Pudlák
źródło
stackoverflow.com/questions/29528624/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
Ten sam problem (dla opcji -x/ xtrace) jest rozwiązany w Pomiń śledzenie wykonania komendy echo?
Scott,

Odpowiedzi:

3

Dokładnie tak samo, jak go aktywujesz: wywoływanie buitin set:

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

Z bash(1)manpage, w SHELL BUILTIN COMMANDSsekcji, polecenie `set ':

-o option-name
The option-name can be one of the following:
    errexit Same as -e.
dawud
źródło
3
Czy istnieje sposób zapisania (wszystkich) tych ustawień i przywrócenia ich później?
Petr Pudlák,
Uruchom set -oznaną bieżącą konfigurację. Podczas ustawiania / wyłączania któregokolwiek z nich w skryptach należy być wyraźnym.
dawud
13

Polecenie set +owyświetla bieżące ustawienia jako polecenia przywracające ten sam stan, np

$ set +o
set +o allexport
set -o braceexpand
set -o emacs
set +o errexit
set +o errtrace
...

Możesz łatwo przywrócić wszystkie opcje później, jeśli zapiszesz te dane wyjściowe w zmiennej powłoki:

SAVED_OPTIONS=$(set +o)
set -e
# do something
eval "$SAVED_OPTIONS"

Bash zawiera również szereg niestandardowych (nie POSIX) opcji, które są regulowane za pomocą shoptpolecenia. Polecenia shopt -pmożna użyć do zapisania tych opcji w podobny sposób.

Jeśli chcesz zapisać i przywrócić tylko jedną opcję, możesz użyć zmiennej środowiskowej $ -, która wyświetla bieżący zestaw opcji jako litery, np.

$ echo $-
himBH

Możesz użyć czegoś takiego do zapisania i przywrócenia określonej opcji:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
Seppo Enarvi
źródło
Pamiętaj, że bardzo ważne jest, aby nie pominąć cytatów wokół „$ SAVED_OPTIONS” w wywołaniu eval.
Matt
3

Użyj pułapki POWRÓT

RETURN pułapki działają również w przypadku skryptów z zewnątrz.

Polecenia określone za pomocą RETURNpułapki są wykonywane przed wznowieniem wykonywania po funkcji powłoki lub skrypcie powłoki wykonanym za pomocą .lub sourcezwraca.

- 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

Test

$ ./main_script.sh 
inside main script
errexit         off
inside sourced script
errexit         on
back inside main script
errexit         off
Robin A. Meade
źródło
2

Przywrócenie poprzednio aktywowanych ustawień można szybko wykonać jako:

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

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

set -$PREV_SETTING

Na odwrót (przywrócenie do stanu wyłączonego) AFAIK nie ma takiego skrótu, a odpowiedź Seppo obejmuje wszystkie przypadki.

F Pereira
źródło
Twój kod jako napisany daje wynik, -bash: set: -i: invalid optionponieważ -iflaga zauważa interaktywną powłokę.
dpw