กับดักได้รับมรดกโดย subshell หรือไม่


14

ฉันลองใช้สคริปต์ต่อไปนี้:

#!/bin/bash
trap 'echo "touching a file" && touch $FILE' EXIT

foo1(){
        echo "foo1"
}
foo(){
        echo "foo"
        export FILE=${FILE:-/tmp/file1}
}
(foo1)
foo

ผลลัพธ์สำหรับสคริปต์ข้างต้นคือ:

[root@usr1 my_tests]# ./test.sh
foo1
foo
touching a file

อย่างไรก็ตามฉันคาดหวังว่ากับดักจะถูกเรียกเมื่อออกจากfoo1เช่นกันซึ่งเรียกว่าใน subshell

  • คาดหวังหรือไม่
  • มีการtrapสืบทอดโดย subshell หรือไม่
  • ถ้าใช่แล้วในกรณีใดที่trapสืบทอดโดย subshell?

ที่เกี่ยวข้อง: unix.stackexchange.com/questions/277090/ …
PSkocik

คำตอบ:


10

ตัวจัดการกับดักจะไม่ถูกสืบทอดโดย subshells สิ่งนี้ถูกระบุโดย POSIX :

เมื่อป้อน subshell กับดักที่ไม่ได้ถูกละเว้นจะถูกตั้งค่าเป็นการกระทำเริ่มต้น

โปรดทราบว่าสัญญาณที่ถูกละเว้น ( trap '' SIGFOO) ยังคงถูกละเว้นใน subshell (และในโปรแกรมภายนอกที่เปิดตัวโดยเชลล์เช่นกัน)


3
ในทุบตีคุณสามารถset -Eมี subshells สืบทอดกับดัก แต่มันเป็นเรื่องยากมากที่จะได้รับสิทธิ (อย่างน้อยในประสบการณ์ของฉัน)
dragon788

ฉันไม่รู้ว่ามันใช้ได้กับกับดักทั้งหมดหรือไม่ ฉันรู้ว่ามันใช้งานได้สำหรับ ERR
yosefrow

4

trapไม่ได้นำเสนอไปยัง subshells แต่บางวิธีอนุญาตให้ subshell รายงานกับดักของเชลล์พาเรนต์และอื่น ๆ ไม่ได้ ฉันทำการทดสอบบางอย่างกับ macos ด้วย bash

ทุบตี GNU รุ่น 4.4.12 (1) - ปล่อย (x86_64-apple-darwin16.3.0):

trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap | cat # trap -- 'echo hello' EXIT
(trap) | cat # trap -- 'echo hello' EXIT
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # trap -- 'echo hello' EXIT

ทุบตี GNU รุ่น 3.2.57 (1) - ปล่อย (x86_64-apple-darwin16):

trap 'echo hello' EXIT
trap # trap -- 'echo hello' EXIT
echo "$(trap)" # trap -- 'echo hello' EXIT
trap > >(cat) # trap -- 'echo hello' EXIT
trap | cat # empty
(trap) | cat # empty
cat < <(trap) # empty
cat <<< "$(trap)" # empty
bash -c 'trap' # empty
trap & # empty

เป็นการดีที่จะรู้ว่าtrap_output="$(trap)"จะทำงานเพื่อดักจับเอาต์พุตของดัก ฉันไม่สามารถคิดวิธีอื่นถ้ามันไม่ทำงานนอกเหนือจากการทำtrap >trap_output_fileเพื่อส่งออกไปยังไฟล์ (Fifo จะไม่ทำงานbash 3.2.57) แล้วอ่านกลับด้วยtrap_output="$(<trap_output_file)"

Fifo จะไม่ทำงานbash 3.2.57เพราะว่างtrap &เปล่าbash 3.2.57แต่ไม่bash 4.4.12

ทุบตี GNU รุ่น 4.4.12 (1) - ปล่อย (x86_64-apple-darwin16.3.0):

mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# trap -- 'echo hello' EXIT

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell

ทุบตี GNU รุ่น 3.2.57 (1) - ปล่อย (x86_64-apple-darwin16):

mkfifo /tmp/fifo; trap >/tmp/fifo & trap_output=$(</tmp/fifo); rm -f /tmp/fifo; echo "$trap_output"
# empty because trap >/tmp/fifo & is empty since it uses trap &

mkfifo /tmp/fifo; trap_output=$(</tmp/fifo) & trap >/tmp/fifo; rm -f /tmp/fifo; echo "$trap_output"
# empty because trap_output=$(</tmp/fifo) sets the variable in a subshell

2

trap คำจำกัดความจะไม่แพร่กระจายไปยังเปลือกย่อย

ยืนยันโดย:

trap "echo bla" 1 2 3"

(trap)


2
เชลล์จำนวนมากจัดการ(trap)เป็นเคสพิเศษเพื่อให้เชลล์ย่อยสามารถรายงาน (แต่ไม่ได้ใช้จริง) กับดักของเชลล์พาเรนต์ ดังนั้นการทดสอบนั้นจึงไม่น่าเชื่อถือเสมอไป
JigglyNaga

จะทำงานร่วมกับบอร์นเชลล์และเป็นสารอนุพันธ์: ksh88, bosh(schily Bourne Shell) heirloom-shและ คุณถูกต้อง: ksh93ประพฤติแตกต่างกัน
schily

มันไม่ทำงานใน bash ซึ่งสคริปต์ดังกล่าวใช้
JigglyNaga

ดีก็ทำงานในทุบตี: ไม่ได้อะไรเอาท์พุทถ้าคุณโทรbash (trap)
schily
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.