Zsh가 다른 쉘의 하위 쉘에서 실행 중일 때 감지

Zsh가 다른 쉘의 하위 쉘에서 실행 중일 때 감지

이것은 아마도 구체적인 답변이 없는 다소 난해한 Zsh 질문입니다.

Zsh가 특정 방식으로 인스턴스화될 때 특정 컨텍스트를 감지하려고 합니다. 이 목적을 위해 일반적으로 사용되는 환경 변수(예: , , 및 )를 고려하면 $SHLVL이를 $ZSH_SUBSHELL수행 $ZSH_EVAL_CONTEXT하는 $-방법은 적어도 내 지식으로는 즉시 명확하지 않습니다 .

다음은 일반적으로 감지 가능한 방식으로 인스턴스화된 Zsh입니다.

export HELLO='world'
zsh -c 'echo "$SHLVL $ZSH_SUBSHELL $ZSH_EVAL_CONTEXT $- $HELLO"'
# 2 0 cmdarg 569X world

감지를 마스킹하는 방식으로 인스턴스화된 Zsh와는 반대로:

export HELLO='world'
(zsh -c 'echo "$SHLVL $ZSH_SUBSHELL $ZSH_EVAL_CONTEXT $- $HELLO"')
# 1 0 cmdarg 569X world

world하위 쉘에서 호출된 Zsh는 의 존재로 표시된 대로 상위 환경의 변수에 액세스할 수 있지만 불행히도 이 경우 해당 값이 도움이 되지 않는다고 $SHLVL속여서 보고합니다 .1$ZSH_SUBSHELL0

표준 탐지 방법을 사용하여 두 번째 사례가 상위 환경에 액세스할 수 있다는 사실을 어떻게 탐지할 수 있습니까? 필요하지 않은 경우 이 목적으로 부모 컨텍스트에 설정한 변수를 확인하여 환경을 오염시키고 싶지 않습니다.

$SHLVL누군가 Zsh가 이를 해독하는 방법과 이 코드를 서브셸에 넣는 이유가 탐지를 마스크하는지 설명할 수 있다면 도움이 될 것입니다. 내가 대략적으로 이해한 바는 서브쉘이 환경(내보낸 모든 것)을 포크하고 $SHLVL내보내지 않는다는 것입니다.

답변1

그건허점(반환)은 1999년에 도입되었습니다.그 변화이제 수정되었습니다.그 변화(범죄))

기본적으로 다음과 같습니다.

(cmd1; cmd2)

zsh서브셸에 대해 하위 프로세스를 포크한 다음 에 대해 포크합니다 cmd1. 그러나 포크의 경우 cmd2서브셸의 마지막 명령이라는 점을 고려하면 zsh포크가 최적화됩니다. 마치 우리가 이미 한 것처럼 보입니다:

(cmd1; exec cmd2)

또는 다른 말로 하면 zsh,절대적인/서서히 나아가는 exec여기.

이제 그 경우에는 오류가 발생합니다.zsh 잊다우리는 서브쉘에 있고 가정합니다.절대적인 exec실제로는종료쉘(로 교체 cmd2)을 사용한 다음 $SHLVLcmd2부모가 더 이상 존재하지 않으므로 감소합니다 zsh.

그러나 여기서는 서브쉘에 있으므로절대적인exec종료 쉘이 없습니다.

이 질문을 제기해 주셔서 감사합니다. 이를 통해 문제를 해결하고 관련 오류를 찾을 수 있습니다.존재하다bash그리고tcsh.

관련 정보