J'ai lu de nombreuses questions sur divers sites d'échange de piles et forums d'aide Unix sur la façon de modifier les options du shell, puis de les restaurer - la plus complète que j'ai trouvée ici est Comment "annuler" un `set -x`?
La sagesse reçue semble être de sauvegarder le résultat de set +o
ou shopt -po
puis eval
de restaurer les paramètres précédents.
Cependant, dans mes propres tests avec bash 3.x et 4.x, l' errexit
option n'est pas enregistrée correctement lors de la substitution de commande.
Voici un exemple de script pour montrer le problème:
set -o errexit
set -o nounset
echo "LOCAL SETTINGS:"
set +o
OLDOPTS=$(set +o)
echo
echo "SAVED SETTINGS:"
echo "$OLDOPTS"
Et la sortie (j'ai supprimé certaines des variables non pertinentes):
LOCAL SETTINGS:
set -o errexit
set -o nounset
SAVED SETTINGS:
set +o errexit
set -o nounset
Cela semble extrêmement dangereux. La plupart des scripts que j'écris dépendent errexit
d'arrêter l'exécution si des commandes échouent. Je viens de localiser un bug dans l'un de mes scripts causé par cela, où la fonction qui était censée être restaurée errexit
à la fin a été remplacée, la redéfinissant par défaut sur off pendant la durée du script.
Ce que j'aimerais pouvoir faire, c'est écrire des fonctions qui peuvent définir des options selon les besoins, puis restaurer correctement toutes les options avant de quitter. Mais il semble que dans le sous-shell invoqué par la substitution de commande, il errexit
ne soit pas hérité.
Je ne sais pas comment économiser le résultat set +o
sans utiliser de substitution de commande ou sauter à travers des cercles FIFO. Je peux lire, $SHELLOPTS
mais ce n'est pas accessible en écriture ou au eval
format.
Je sais qu'une alternative est d'utiliser une fonction de sous - shell , mais cela introduit beaucoup de maux de tête pour pouvoir enregistrer la sortie ainsi que transmettre plusieurs variables.
Probablement lié: /programming/29532904/bash-subshell-errexit-semantics (il semble qu'il existe une solution de contournement pour bash 4.4 et plus, mais je préfère avoir une solution portable)
shopt
options de l'ensemble bash (comme nullglob).Réponses:
Ce que vous faites devrait fonctionner. Mais bash désactive l'
errexit
option dans les substitutions de commandes, il conserve donc toutes les options sauf celle-ci. Ceci est spécifique à bash et spécifique à l'errexit
option. Bash se conserveerrexit
lors de l'exécution en mode POSIX. Depuis bash 4.4, bash ne s'efface pas non pluserrexit
dans une substitution de commande si elleshopt -s inherit_errexit
est en vigueur.Étant donné que l'option est désactivée avant l'exécution de tout code à l'intérieur de la substitution de commande, vous devez la vérifier à l'extérieur.
Si vous n'aimez pas cette complexité, utilisez plutôt zsh.
la source
bash4.4
a maintenantlocal -
(à laash
) comme équivalent àzsh
l »setopt localoptions
(ou ce que ksh88 fait par défaut)shopt -s lastpipe; set +o | IFS= read -rd '' OLDOPTS || :
(les deux ensembles d'options sont une autrebash
idiosyncrasie de).OLDOPTS="$(set +o); set -$-"
.Après avoir essayé l'ancien de ce qui précède sur alpine 3.6, j'ai maintenant adopté l'approche beaucoup plus simple suivante:
selon la documentation, "$ -" contient la liste des options actuellement actives. Semble fonctionner très bien, est-ce que je manque quelque chose?
la source
set -uf
)errexit
se propage en substitutions de processus.Vérifier:
Version basique:
la source
La solution simple consiste à ajouter le
errexit
paramètre àOLDOPTS
:Terminé.
la source
[[ -o errexit ]]
(ksh / bash / zsh) et[ -o errexit ]
(bash / ksh / yash)shopt
s'agit d'une commande valide pour bash, il n'y a aucune raison valable de l'éviter (je ne fais que déterminer votre façon de rédiger les réponses). Pas un changement significatif. @ StéphaneChazelas