I had expected that
exitwould 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
exitfnso 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.