Як правильно відновити налаштування під час запуску сценарію за допомогою "source"?


9

Я пишу сценарій, який потрібно виконати за допомогою source, оскільки його завдання - модифікувати середовище. Під час сценарію я хочу використовувати set -eтак, щоб будь-яка помилка зупиняла сценарій. Сценарій виглядає приблизно так:

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

Проблема в тому, що set -eприродно залишається в силі після закінчення сценарію. Як я можу гарантувати, що змінена setопція буде належним чином відновлена ​​до свого попереднього значення, коли сценарій припиняється (будь-яким чином - або успішно завершившись, або помилка)?



Це ж питання (для -x/ xtraceопції) вирішується в сліді виконання придушити для команди echo?
Скотт

Відповіді:


3

Точно так само, як ви його активуєте: викликаючи бутін 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
Чи існує спосіб зберегти (усі) ці налаштування та відновити їх згодом?
Петро Пудлак

Перейдіть set -oдо відомих ваших поточних налаштувань. Будьте чіткими, встановлюючи / відміняючи будь-який з них у своїх сценаріях.
dawud

13

Команда set +oперераховує поточні налаштування як команди, які відновлюють той самий стан, наприклад

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

Ви можете легко відновити всі параметри пізніше, якщо ви збережете цей вихід у змінній оболонки:

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

Зауважте, що дуже важливо не пропустити цитати навколо "$ SAVED_OPTIONS" у виклику eval.
Метт

3

Використовуйте ПОВЕРНЕННУ пастку

RETURN пастки працюють і для джерел скриптів.

Команди, вказані в RETURNпастці, виконуються до того, як виконання буде відновлено після функції оболонки або сценарію оболонки, виконаного з .або sourceповерненням.

- 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 не існує такого ярлика, і відповідь Сеппо охоплює всі випадки.


Ваш код, як написаний, дає результат, -bash: set: -i: invalid optionоскільки -iпрапор зазначає інтерактивну оболонку.
dpw
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.