Ich habe viele Fragen auf verschiedenen Stack-Exchange-Sites und Unix- Hilfeforen gelesen, wie man Shell-Optionen ändert und sie dann wiederherstellt .
Die empfangene Weisheit scheint entweder zu sein , um das Ergebnis zu speichern aus set +o
oder shopt -po
und dann eval
später die vorherigen Einstellungen wiederherzustellen.
Bei meinen eigenen Tests mit bash 3.x und 4.x wird die errexit
Option jedoch beim Ersetzen von Befehlen nicht korrekt gespeichert.
Hier ist ein Beispielskript, um das Problem zu zeigen:
set -o errexit
set -o nounset
echo "LOCAL SETTINGS:"
set +o
OLDOPTS=$(set +o)
echo
echo "SAVED SETTINGS:"
echo "$OLDOPTS"
Und Ausgabe (ich habe einige der irrelevanten Variablen herausgeschnitten):
LOCAL SETTINGS:
set -o errexit
set -o nounset
SAVED SETTINGS:
set +o errexit
set -o nounset
Das scheint extrem gefährlich. Die meisten Skripte, die ich schreibe, hängen davon ab errexit
, die Ausführung anzuhalten, wenn Befehle fehlschlagen. Ich habe gerade einen Fehler in einem meiner Skripte gefunden, der dadurch verursacht wurde, dass die Funktion, die errexit
am Ende wiederhergestellt werden sollte, ihn überschrieb und ihn für die Dauer des Skripts auf den Standardwert " Aus" zurücksetzte.
Ich möchte in der Lage sein, Funktionen zu schreiben, mit denen Optionen nach Bedarf festgelegt und dann alle Optionen vor dem Beenden ordnungsgemäß wiederhergestellt werden können. Aber es scheint, als ob in der Subshell, die durch die Befehlsersetzung aufgerufen wird, errexit
nicht vererbt wird.
Ich weiß nicht, wie ich das Ergebnis sparen kann, set +o
ohne Befehlsersetzung zu verwenden oder durch FIFO-Rahmen zu springen. Ich kann lesen, $SHELLOPTS
aber es ist nicht beschreibbar oder im eval
-able-Format.
Ich weiß, dass eine Alternative darin besteht, eine Subshell-Funktion zu verwenden , aber das bringt viele Kopfschmerzen mit sich, wenn es darum geht, Ausgaben zu protokollieren und mehrere Variablen zurückzugeben.
Wahrscheinlich verwandt: /programming/29532904/bash-subshell-errexit-semantics (anscheinend gibt es eine Problemumgehung für Bash 4.4 und höher, aber ich hätte lieber eine tragbare Lösung)
shopt
Set-Optionen (wie nullglob) nicht wiederhergestellt .Antworten:
Was Sie tun, sollte funktionieren. Aber bash deaktiviert die
errexit
Option bei Befehlsersetzungen, sodass alle Optionen außer dieser beibehalten werden. Dies ist spezifisch für Bash und spezifisch für dieerrexit
Option. Bash bleibt erhalten,errexit
wenn es im POSIX-Modus ausgeführt wird. Seit Bash 4.4 wird Bash aucherrexit
bei einer Befehlsersetzung nicht gelöscht, wenn diesshopt -s inherit_errexit
wirksam ist.Da die Option deaktiviert ist, bevor Code innerhalb der Befehlsersetzung ausgeführt wird, müssen Sie ihn außerhalb überprüfen.
Wenn Ihnen diese Komplexität nicht gefällt, verwenden Sie stattdessen zsh.
quelle
bash4.4
jetztlocal -
(à laash
) als Äquivalent zuzsh
'ssetopt localoptions
(oder was ksh88 standardmäßig tut)shopt -s lastpipe; set +o | IFS= read -rd '' OLDOPTS || :
(die beiden Optionssätze sind eine weiterebash
Besonderheit).OLDOPTS="$(set +o); set -$-"
.Nachdem ich das Alte von oben auf alpine 3.6 ausprobiert habe, habe ich jetzt den folgenden viel einfacheren Ansatz gewählt:
Gemäß Dokumentation enthält "$ -" die Liste der derzeit aktiven Optionen. Scheint großartig zu funktionieren, vermisse ich etwas?
quelle
set -uf
)errexit
wird in Prozesssubstitutionen propagiert.Prüfen:
Bash-Version:
quelle
Die einfache Lösung besteht darin, die
errexit
Einstellung an Folgendes anzuhängenOLDOPTS
:Erledigt.
quelle
[[ -o errexit ]]
(ksh / bash / zsh) und[ -o errexit ]
(bash / ksh / yash)shopt
ist ein gültiger Befehl für Bash, es gibt keinen sinnvollen Grund, dies zu vermeiden (ich bin nur eine Frage Ihrer persönlichen Präferenz, wie Antworten geschrieben werden sollen). Keine sinnvolle Veränderung. @ StéphaneChazelas