Trap handling dan subshell implisit dalam skrip shell

12

Katakanlah Anda memiliki skrip shell yang menjalankan semacam kode pembersihan melalui EXITjebakan, seperti ini:

#!/bin/bash

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

trap mytrap exit

echo I am at the end of the script.

Ini akan, seperti yang diharapkan, dicetak It's a trap!ketika skrip keluar:

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

Anda memodifikasi skrip untuk menambahkan fungsi yang menghasilkan beberapa output yang akhirnya disalurkan ke perintah lain, seperti ini:

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

Karena pipa, kode di myfuncdijalankan dalam subkulit ... dan subkulit tampaknya tidak mewarisi trapperilaku induk, yang berarti jika Anda melakukan tindakan apa pun di sini yang harus dibersihkan oleh kode perangkap Anda yang akan menang ' tidak terjadi.

Jadi Anda coba ini:

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

Dan masih gagal memicu mytrapketika subshell keluar. Ternyata Anda perlu eksplisit exit, seperti ini:

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

Dengan kode di atas, mytrapakan terpicu tepat saat keluar dari subkulit:

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

Apakah itu perilaku yang diharapkan? Saya terkejut oleh beberapa hal di sini:

  • trap pengaturan tidak diwariskan oleh subkulit
  • keluar tersirat dari subkulit tampaknya tidak memicu EXIT jebakan
larsks
sumber

Jawaban:

8

Bash trapbuiltin memungkinkan kata kunci RETURN. Karena itu ubah:

trap mytrap EXIT

untuk:

trap mytrap RETURN

Lihat pembahasan trapdi shell-builtin

JRFerguson
sumber