Como restaurar as configurações corretamente ao executar um script usando "fonte"?

9

Estou escrevendo um script que precisa ser executado usando source, porque sua tarefa é modificar o ambiente. Durante o script, quero usar set -epara que qualquer erro pare o script. O script fica assim:

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

O problema é que, set -enaturalmente, permanece em vigor após a conclusão do script. Como posso garantir que a setopção alterada seja restaurada adequadamente ao seu valor anterior quando o script for interrompido (de alguma forma - seja com êxito ou com erro)?

Petr Pudlák
fonte
O mesmo problema (para a opção -x/ xtrace) é abordado em Suprimir rastreamento de execução para o comando echo?
Scott

Respostas:

3

Exatamente da mesma maneira que você a ativa: chamando o buitin set:

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

Na página de bash(1)manual, na SHELL BUILTIN COMMANDSseção, comando `set ':

-o option-name
The option-name can be one of the following:
    errexit Same as -e.
dawud
fonte
3
Existe uma maneira de salvar (todas) essas configurações e restaurá-las mais tarde?
Petr Pudlák
Execute set -opara conhecer sua configuração atual. Seja explícito ao definir / desabilitar qualquer um deles em seus scripts.
dawud 21/09/2013
12

O comando set +olista as configurações atuais como comandos que restauram o mesmo estado, por exemplo

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

Você pode restaurar facilmente todas as opções posteriormente, se salvar esta saída em uma variável do shell:

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

O Bash também inclui várias opções não padrão (não POSIX) que são ajustadas usando o shoptcomando O comando shopt -ppode ser usado para salvar essas opções de maneira semelhante.

Se você deseja salvar e restaurar apenas uma opção, pode usar a variável de ambiente $, que lista o conjunto de opções atual como letras, por exemplo

$ echo $-
himBH

Você pode usar algo assim para salvar e restaurar uma opção específica:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
Seppo Enarvi
fonte
Observe que é muito importante não perder as aspas em torno de "$ SAVED_OPTIONS" na chamada de avaliação.
Matt
3

Use uma armadilha RETURN

RETURN armadilhas também funcionam para scripts de origem.

Os comandos especificados com uma RETURNinterceptação são executados antes que a execução seja retomada após uma função shell ou um script shell executado com .ou sourceretorna.

- 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

Teste

$ ./main_script.sh 
inside main script
errexit         off
inside sourced script
errexit         on
back inside main script
errexit         off
Robin A. Meade
fonte
2

A restauração das configurações ativadas anteriores pode ser feita rapidamente como:

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

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

set -$PREV_SETTING

Ao contrário (restaurar para o estado desativado), AFAIK não existe um atalho e a resposta do Seppo abrange todos os casos.

F Pereira
fonte
Seu código como escrito produz -bash: set: -i: invalid optionporque o -isinalizador observa um shell interativo.
dpw