Detectar quando o Zsh está rodando dentro da subcamada de outro shell

1

Esta é uma questão Zsh ligeiramente esotérica, da qual pode não haver uma resposta concreta.

Eu estou tentando detectar um contexto particular de um Zsh quando instanciado de uma maneira particular. Como fazer isso não é imediatamente óbvio, considerando as variáveis de ambiente comumente usadas para esse fim (como $SHLVL , $ZSH_SUBSHELL , $ZSH_EVAL_CONTEXT e $- ), pelo menos tanto quanto eu saiba.

Aqui está um Zsh instanciado de uma forma normalmente detectável:

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

Ao contrário de um Zsh instanciado de uma forma que obscurece a detecção:

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

O Zsh chamado dentro da subshell tem acesso às variáveis do ambiente pai, como é evidente pela presença de world , mas $SHLVL é induzido a reportar 1 e infelizmente $ZSH_SUBSHELL , com um valor de 0 , não é de ajuda neste caso.

Como posso detectar, usando métodos de detecção padrão, o fato de que o segundo caso tem acesso a um ambiente pai? Eu não quero ter que confiar na verificação de variáveis definidas por mim mesmo no contexto pai que sujam o ambiente apenas para esse propósito, se eu não precisar.

Talvez me ajude se alguém puder explicar como o Zsh decifra o $SHLVL e por que colocar esse código em uma subcamada obscurece essa detecção. Minha compreensão é que o subshell bifurca o ambiente (tudo o que é exportado) e que $SHLVL não é exportado.

    
por leoj 22.08.2016 / 03:54

1 resposta

3

Esse foi um bug (regressão) introduzido em 1999 por essa mudança e agora corrigida (por essa mudança ( confirmar ))

Basicamente, em:

(cmd1; cmd2)

zsh bifurca um processo filho para o subshell e, em seguida, outro processo para cmd1 . Mas para cmd2 , dado que é o último comando no subshell, zsh otimiza o fork. É como se tivéssemos feito:

(cmd1; exec cmd2)

Ou, em outras palavras, zsh faz um implícito / fake exec aqui.

Agora, o erro era que, nesse caso, zsh esqueceu que estávamos em uma subshell e assumimos que implícito exec estava realmente terminando o shell (substituindo-o por cmd2 ) e, em seguida, decrementando $SHLVL , pois o pai de cmd2 não seria mais zsh .

Aqui, no entanto, estamos em um subshell, portanto, implícito exec não está finalizando o shell.

Obrigado por mencionar isso. Isso permitiu corrigi-lo e encontrar bugs relacionados em bash e tcsh .

    
por 03.09.2016 / 17:12

Tags