Bash에서 내가 서브셸에 있는지 어떻게 감지합니까?

Bash에서 내가 서브셸에 있는지 어떻게 감지합니까?

exit터미널을 종료하는 것을 방지하기 위해 내장 함수의 기능을 대체하는 함수를 작성하려고 합니다 .

환경 변수를 사용해 보았 SHLVL으나 서브셸에서는 변경되지 않는 것 같습니다.

$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2

내 기능은 다음과 같습니다.

exit () {
    if [[ $SHLVL -eq 1 ]]; then
        printf '%s\n' "Nice try!" >&2
    else
        command exit
    fi
}

exit하지만 이 방법으로 는 서브셸에서 사용할 수 없습니다 .

$ exit
Nice try!
$ (exit)
Nice try!

내가 서브셸에 있는지 감지할 수 있는 좋은 방법이 있습니까?

답변1

$BASHPIDBash에서는 비교할 수 있습니다$$

$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$   if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell

Bash를 사용하지 않는 경우 $$하위 쉘에서 변경되지 않은 상태로 유지되어야 하므로 실제 프로세스 ID를 얻으려면 다른 방법이 필요합니다.

실제 pid를 얻는 한 가지 방법은 sh -c 'echo $PPID'. 그냥 평범한 곳에 놔두면 ( … )쉘이 이미 포크에 최적화되어 있어서 작동하지 않는 것처럼 보일 수도 있습니다. 추가 no-op 명령을 시도하여 ( : ; sh -c 'echo $PPID'; : )서브셸이 최적화하기에는 너무 복잡하다고 생각하게 만드세요. 신용은 간다스택 오버플로의 John1024이 방법의 경우.

답변2

어때요 BASH_SUBSHELL?

BASH_SUBSHELL       해당 환경에서
      쉘이 실행을 시작할 때 각 서브쉘 또는 서브쉘 환경에 하나를 추가합니다.
초기값은 0입니다.

$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1

답변3

[댓글이어야 하는데 제가 쓴 댓글은 운영자에 의해 삭제되는 경향이 있어서 답변으로 남고, 삭제되더라도 참고용으로 사용할 수 있습니다.]

1로만 설정할 수 있으므로 사용하기에 BASH_SUBSHELL완전히 신뢰할 수 없습니다.일부서브쉘이지만 모든 서브쉘에 있는 것은 아닙니다.

$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0

파이프 명령을 실행하는 하위 프로세스가 파이프라인이 아님을 선언하는 경우진짜진정한 서브셸의 경우 다음 man bash코드 조각을 고려하세요.

파이프라인의 각 명령은 별도의 프로세스(즉, 하위 셸에서)로 실행됩니다.

그리고 실질적인 의미 - 중요한 것은 용어상의 논쟁이 아니라 스크립트 조각이 하위 프로세스에서 실행되는지 여부입니다.

이 질문에 대한 답변에서 이미 설명했듯이 유일한 해결책은질문$BASHPID이식성 과 동일 $$하지만 훨씬 덜 효율적 인지 확인하는 것입니다 .

if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
    echo you\'re in a subshell
fi

관련 정보