¿Cómo restaurar correctamente la configuración cuando se ejecuta un script usando "fuente"?

9

Estoy escribiendo un script que debe ejecutarse usando source, porque su tarea es modificar el entorno. Durante el script, quiero usarlo set -epara que cualquier error detenga el script. El guión se ve así:

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

El problema es que, set -enaturalmente, permanece vigente una vez que finaliza el script. ¿Cómo puedo asegurarme de que la setopción alterada se restaure correctamente a su valor anterior cuando el script se detiene (de alguna manera, ya sea completando con éxito o en caso de error)?

Petr Pudlák
fuente
stackoverflow.com/questions/29528624/…
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
¿Se aborda el mismo problema (para la opción -x/ xtrace) en Suprimir rastreo de ejecución para comando echo?
Scott

Respuestas:

3

Exactamente de la misma manera que lo activas: llamando al buitin set:

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

Desde la página de bash(1)manual, debajo de la SHELL BUILTIN COMMANDSsección, comando `set ':

-o option-name
The option-name can be one of the following:
    errexit Same as -e.
Dawud
fuente
3
¿Hay alguna manera de guardar (todas) estas configuraciones y restaurarlas más tarde?
Petr Pudlák
Ejecute set -opara conocer su configuración actual. Sea explícito al configurar / desarmar cualquiera de ellos en sus scripts.
dawud
12

El comando set +oenumera la configuración actual como comandos que restauran el mismo estado, p. Ej.

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

Puede restaurar fácilmente todas las opciones más adelante, si guarda esta salida en una variable de shell:

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

Bash también incluye una serie de opciones no estándar (no POSIX) que se ajustan mediante el shoptcomando. El comando shopt -pse puede usar para guardar estas opciones de manera similar.

Si solo desea guardar y restaurar una opción, puede usar la variable de entorno $ -, que enumera el conjunto actual de opciones como letras, p. Ej.

$ echo $-
himBH

Podría usar algo como esto para guardar y restaurar una opción en particular:

[[ $- = *e* ]]
SAVED_ERREXIT=$?
set -e
# do something
(( $SAVED_ERREXIT )) && set +e
Seppo Enarvi
fuente
Tenga en cuenta que es muy importante no perderse las comillas alrededor de "$ SAVED_OPTIONS" en la llamada de evaluación.
Matt
3

Use una trampa de RETORNO

RETURN las trampas también funcionan para scripts de origen.

Los comandos especificados con una RETURNtrampa se ejecutan antes de que se reanude la ejecución después de una función de shell o un script de shell ejecutado con .o sourcedevuelve.

- 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

Prueba

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

La restauración de configuraciones activadas anteriores se puede hacer rápidamente como:

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

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

set -$PREV_SETTING

Al revés (restaurar al estado apagado) AFAIK no existe un atajo y la respuesta de Seppo cubre todos los casos.

F Pereira
fuente
Su código como escrito rinde -bash: set: -i: invalid optionporque la -ibandera observa un shell interactivo.
dpw