Manipulação de interceptação e subshells implícitos em scripts de shell

12

Digamos que você tenha um script de shell que execute algum tipo de código de limpeza através de uma EXITarmadilha, como esta:

#!/bin/bash

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

trap mytrap exit

echo I am at the end of the script.

Isso, como esperado, será impresso It's a trap!quando o script sair:

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

Você modifica o script para adicionar uma função que gera alguma saída que acaba sendo canalizada para outro comando, como este:

#!/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.

Por causa do canal, o código myfuncé executado em um subshell ... e os subshells não parecem herdar o trapcomportamento do pai, o que significa que, se você executar alguma ação aqui que deve ser limpa pelo seu código de captura que ganhou ' isso não acontece.

Então você tenta o seguinte:

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

E ainda não dispara mytrapquando o subshell sai. Acontece que você precisa de um explícito exit, assim:

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

Com o código acima, mytrapserá acionado adequadamente ao sair do subshell:

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

Esse comportamento é esperado? Fiquei surpreso com várias coisas aqui:

  • trap as configurações não foram herdadas por subshells
  • saída implícita de um subshell não parece acionar uma EXIT armadilha
larsks
fonte

Respostas:

8

O bash trapbuiltin permite a palavra-chave RETURN. Daí a mudança:

trap mytrap EXIT

para:

trap mytrap RETURN

Veja a discussão trapem shell-builtins

JRFerguson
fonte