BASH 하위 쉘에 대해 EXIT 트랩이 정의되어 있는지 확인하는 방법은 무엇입니까?

BASH 하위 쉘에 대해 EXIT 트랩이 정의되어 있는지 확인하는 방법은 무엇입니까?

다음은 BASH 스크립트의 예입니다.

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    trap -p EXIT >&2
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

실행되면 다음과 같은 출력이 생성됩니다.

subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
trap -- 'exithdl' EXIT
returned from fun
exiting
in exithdl subshell=0

서브쉘 0과 1의 명령은 trap -p EXIT >&2정의된 EXIT 트랩을 표시하지만 이 exithdl기능은 서브쉘 0이 종료된 후에만 실행됩니다. exithdl종료 후 서브쉘 1이 실행되지 않도록 하는 방법이 있습니까 ? 즉, fun이 함수가 EXIT 트랩 없이 서브쉘 1을 결정할 수 있도록 하나 이상의 명령을 추가하는 것이 가능합니까?

예제에서 EXIT 트랩은 하위 쉘 0에 대해 정의되지만 하위 쉘 1에 대해서는 정의되지 않습니다. 이 trap -p EXIT명령은 두 서브셸 모두에서 실행될 때 정확히 동일한 출력을 표시합니다. 따라서 trap -p EXIT특정 서브쉘에 트랩이 있는지 확인하는 데에는 사용할 수 없다고 가정합니다. 나는 trap -p EXIT명령이 실행될 때 EXIT 트랩의 존재를 표시한다는 것을 인정 fun하지만, fun이 반환될 때 EXIT 트랩이 실행된다면 그것은 나타나지 않을 것입니다. 내가 뭐 놓친 거 없니?

답변1

배쉬 3을 사용하는 경우

대답은 사용 중인 bash 버전에 따라 다릅니다. 예를 들어 내 Mac에는 macOS High Sierra가 기본적으로 설치되어 있습니다 GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17). 이 경우 아래와 같이 trap -p EXIT >&2함수의 명령에 괄호를 추가하면 문제를 해결할 수 있습니다 .fun

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    (trap -p EXIT >&2) # <--- See Here
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

아래 표시된 결과 출력에는 더 이상 트랩이 fun있는 기능이 표시되지 않습니다 .EXIT

subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
returned from fun
exiting
in exithdl subshell=0

이 방법은 다른 트랩의 하위 집합에도 적용됩니다. 예를 들어, 이 하위 집합에는 , 및 INT트랩이 포함됩니다 QUIT. 그러나 이 하위 집합에는 기타 문제가 포함되지 않습니다.TERMCHLDHUP

Bash 4 및 5를 사용하는 경우

VirtualBox에 Ubuntu 18과 19도 설치했습니다. 이러한 운영 체제는 기본적으로 각각 GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)및 를 사용합니다 GNU bash, version 5.0.11(1)-release (x86_64-pc-linux-gnu). 위의 변경 사항을 적용하여 스크립트를 실행하면 결과는 원래 출력과 동일합니다. 그러나 이러한 최신 버전의 bash의 경우 trap아래와 같이 기능에서 명령 앞에 명령을 추가하면 문제를 해결할 수 있습니다 .trap -p EXIT >&2fun

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    trap -- KILL # <--- See Here
    trap -p EXIT >&2
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

트랩을 변경할 수 없기 때문에 이 trap -- KILL명령이 선택되었습니다 . KILL그러면 위 이미지와 동일한 출력이 생성됩니다. 이 방법은 다른 트랩에도 적용됩니다.

결론적으로

exitTrap현재 트랩을 정의하는 데 사용되는 명령에 대한 변수를 설정 하려면 (예를 들어) EXIT아래 표시된 스크립트를 사용하십시오. 이것은 bash 3, 4 및 5에서 작동합니다.

trap -- KILL
exitTrap="$( (trap -p EXIT) )"

관련 정보