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).Respuestas:
Lo que estás haciendo debería funcionar. Pero bash desactiva la
errexit
opción en las sustituciones de comandos, por lo que conserva todas las opciones excepto esta. Esto es específico de bash y específico de laerrexit
opción. Bash conservaerrexit
cuando se ejecuta en modo POSIX. Desde bash 4.4, bash tampoco se borraerrexit
en una sustitución de comando sishopt -s inherit_errexit
está vigente.Dado que la opción está desactivada antes de que se ejecute ningún código dentro de la sustitución del comando, debe verificarlo afuera.
Si no te gusta esta complejidad, usa zsh en su lugar.
fuente
bash4.4
ahora tienelocal -
(à laash
) como equivalente azsh
'ssetopt localoptions
(o lo que ksh88 hace por defecto)shopt -s lastpipe; set +o | IFS= read -rd '' OLDOPTS || :
(los dos conjuntos de opciones son otra debash
las idiosincrasias de).OLDOPTS="$(set +o); set -$-"
.Después de probar lo anterior en alpine 3.6, ahora he tomado el siguiente enfoque mucho más simple:
Según la documentación, "$ -" contiene la lista de opciones activas actualmente. Parece funcionar muy bien, ¿me estoy perdiendo algo?
fuente
set -uf
)errexit
se propaga en sustituciones de proceso.Cheque:
Versión bash:
fuente
La solución simple es agregar la
errexit
configuración aOLDOPTS
:Hecho.
fuente
[[ -o errexit ]]
(ksh / bash / zsh) y[ -o errexit ]
(bash / ksh / yash)shopt
es un comando válido para bash, no hay una razón significativa para evitarlo (solo es una cuestión de su preferencia personal de cómo se deben escribir las respuestas). No es un cambio significativo. @ StéphaneChazelas