I had expected that
exit
would have the effect of killing the current process (i.e. the one with PID given by$$
)
“O processo atual” não é a mesma coisa que “o processo com PID dado por $$
”. exit
sai do subshell , ou o shell original se não for chamado em um subshell.
Certas construções, como o conteúdo de ( … )
(agrupamento com subshell), substituições de comando ( $(…)
ou '…'
) e cada lado de um pipe (ou apenas o lado esquerdo em algumas camadas) , corra em uma subcamada. Um subshell se comporta como se fosse um processo separado criado com fork()
, e geralmente é implementado dessa forma (alguns shells não usam subprocessos em algumas circunstâncias, como uma otimização de desempenho). O subshell possui sua própria cópia de variáveis, seus próprios redirecionamentos, etc. Chamar exit
sai do subshell, assim como a função exit()
na biblioteca C padrão sai do processo. Para mais informações sobre sub-unidades, consulte O que é um subshell (no contexto da documentação do make)? , Qual é a diferença exata entre um" subshell "e um" processo filho "? e É $ () um subshell? .
$$
é sempre o ID do processo original do shell. Não muda em um subshell. Alguns shells têm uma variável que muda em um subshell, por exemplo $BASHPID
no bash e mksh, ou ${.sh.subshell}
no ksh ou $ZSH_SUBSHELL
ou $sysparams[pid]
no zsh¹.
is there a way to write
exitfn
so that it exits the surrounding script even when invoked within a pipeline?
Não exatamente. Você precisará fazer mais trabalho, seja no ponto em que o script cria subshell ou no nível superior, ou ambos. Consulte saia do shell script de um subshell para aproximações.
¹ Cuidado, embora contrário a outros shells, zsh
executa expansões em pipelines no processo pai (da esquerda para a direita), não em cada um dos membros dos pipelines: zsh -c 'echo $ZSH_SUBSHELL | cat'
outputs 0
(mesmo que echo
é executado em um processo filho) e zsh -c 'n=0; echo $((++n)) | echo $((++n))'
produz 2.