Trap-Behandlung und implizite Subshells in Shell-Skripten

12

Angenommen, Sie haben ein Shell-Skript, das eine Art Bereinigungscode über eine EXITFalle ausführt, wie folgt:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

trap mytrap exit

echo I am at the end of the script.

Dies wird erwartungsgemäß ausgedruckt, It's a trap!wenn das Skript beendet wird:

$ sh myscript
I am at the end of the script.
It's a trap!

Sie ändern das Skript, um eine Funktion hinzuzufügen, die eine Ausgabe generiert, die letztendlich an einen anderen Befehl weitergeleitet wird, wie folgt:

#!/bin/bash

mytrap () {
  echo "It's a trap!" >&2
}

myfunc () {
  echo "I've got a bad feeling about this..."
}

trap mytrap exit

myfunc | cat > /dev/null

echo I am at the end of the script.

Aufgrund der Pipe wird der Code in myfuncin einer Subshell ausgeführt ... und Subshells scheinen das trapVerhalten des übergeordneten Elements nicht zu erben. Dies bedeutet, wenn Sie hier Aktionen ausführen, die von Ihrem gewonnenen Trap-Code bereinigt werden sollten. ' t passieren.

Also versuchst du das:

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
}

Und es wird immer noch nicht ausgelöst, mytrapwenn die Subshell beendet wird. Es stellt sich heraus, dass Sie eine explizite exitwie folgt benötigen :

myfunc () {
  trap mytrap EXIT
  echo "I've got a bad feeling about this..."
  exit
}

mytrapWird mit dem obigen Code beim Verlassen der Subshell entsprechend ausgelöst:

$ sh myscript 
It's a trap!
I am at the end of the script.
It's a trap!

Ist das erwartetes Verhalten? Ich war hier von mehreren Dingen überrascht:

  • trap Einstellungen wurden nicht von Subshells geerbt
  • Das implizite Verlassen einer Unterschale scheint keine EXIT Falle auszulösen
Larsks
quelle

Antworten:

8

Das trapeingebaute Bash erlaubt das Schlüsselwort RETURN. Daher ändern:

trap mytrap EXIT

zu:

trap mytrap RETURN

Siehe die Diskussion trapin Shell-Builtins

JRFerguson
quelle