서브 쉘에 있는지 어떻게 알 수 있습니까? ]]; then

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!

서브 쉘에 있는지 여부를 감지하는 좋은 방법은 무엇입니까?



답변

bash에서는 다음과 비교할 $BASHPID수 있습니다.$$

$ ( 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

배쉬가 아닌 경우 $$, 서브 쉘에서 동일하게 유지되어야하므로 실제 프로세스 ID를 얻는 다른 방법이 필요합니다.

실제 pid를 얻는 한 가지 방법은 sh -c 'echo $PPID'입니다. ( … )껍질을 평평 하게 넣으면 껍질이 포크를 최적화하여 작동하지 않는 것처럼 보일 수 있습니다. ( : ; sh -c 'echo $PPID'; : )서브 쉘이 너무 복잡하여 최적화 할 수 없다고 생각되도록 추가 no-op 명령 을 시도하십시오 . 이 접근법에 대한 크레딧은 스택 오버플 로에서 John1024 에게 전달됩니다 .


답변

어때요 BASH_SUBSHELL?

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

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


답변

[이것은 의견 이었음에 틀림 없다. 그러나 나의 의견은 중재자에 의해 삭제되는 경향이 있으므로, 삭제 된 경우에도이를 참조로 사용할 수있는 답변으로 유지 될 것이다]

사용은 BASH_SUBSHELL그것이 단지 1로 설정할 수로 완전히 신뢰할 수없는 몇 가지 모든 서브 쉘에서, 서브 쉘.

$ (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


답변