He leído muchas preguntas en varios sitios de intercambio de pila y foros de ayuda de Unix sobre cómo modificar las opciones de shell y luego restaurarlas. La más completa que encontré aquí es ¿Cómo "deshacer" un `set -x`?
La sabiduría recibida parece ser guardar el resultado de set +o
o shopt -po
y luego eval
restaurar la configuración anterior.
Sin embargo, en mis propias pruebas con bash 3.xy 4.x, la errexit
opción no se guarda correctamente al realizar la sustitución de comandos.
Aquí hay un script de ejemplo para mostrar el problema:
set -o errexit
set -o nounset
echo "LOCAL SETTINGS:"
set +o
OLDOPTS=$(set +o)
echo
echo "SAVED SETTINGS:"
echo "$OLDOPTS"
Y salida (recorté algunas de las variables irrelevantes):
LOCAL SETTINGS:
set -o errexit
set -o nounset
SAVED SETTINGS:
set +o errexit
set -o nounset
Esto parece extremadamente peligroso. La mayoría de los scripts que escribo dependen errexit
de detener la ejecución si alguno de los comandos falla. Acabo de localizar un error en uno de mis scripts causado por esto, donde la función que se suponía que debía restaurarse errexit
al final terminó anulándolo, volviéndolo al valor predeterminado de apagado durante la duración del script.
Lo que me gustaría poder hacer es escribir funciones que puedan configurar las opciones según sea necesario y luego restaurar todas las opciones correctamente antes de salir. Pero parece que en la subshell invocada por la sustitución del comando errexit
no se hereda.
No sé cómo ahorrar el resultado set +o
sin utilizar la sustitución de comandos o saltar a través de los aros FIFO. Puedo leer, $SHELLOPTS
pero no se puede escribir ni escribir en eval
formato.
Sé que una alternativa es usar una función de subshell , pero eso introduce muchos dolores de cabeza para poder registrar la salida y transferir múltiples variables.
Probablemente relacionado: /programming/29532904/bash-subshell-errexit-semantics (parece que hay una solución para bash 4.4 y versiones posteriores, pero prefiero tener una solución portátil)
shopt
opciones de bash set (como nullglob).