Estou tentando escrever uma função para substituir a funcionalidade do exit
builtin para me impedir de sair do terminal.
Eu tentei usar a SHLVL
variável de ambiente, mas ela não parece mudar nos subshells:
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Minha função é a seguinte:
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
Isso não me permitirá usar exit
dentro de subshells:
$ exit
Nice try!
$ (exit)
Nice try!
Qual é um bom método para detectar se estou ou não em um subshell?
No bash, você pode comparar
$BASHPID
com$$
Se você não estiver no bash,
$$
deve permanecer o mesmo em um subshell, portanto, precisará de outra maneira de obter seu ID de processo real.Uma maneira de obter seu pid real é
sh -c 'echo $PPID'
. Se você apenas colocar isso em uma planície( … )
, pode parecer que não funciona, pois seu shell otimizou o fork. Tente comandos extras no-op( : ; sh -c 'echo $PPID'; : )
para fazê-lo pensar que o subshell é muito complicado para otimizar. O crédito vai para John1024 no Stack Overflow por essa abordagem.Que tal
BASH_SUBSHELL
?[isso deveria ter sido um comentário, mas meus comentários tendem a ser deletados pelos moderadores, então isso vai ficar como uma resposta que eu poderia usar como referência mesmo se deletado]
O uso
BASH_SUBSHELL
não é completamente confiável, pois é definido apenas como 1 em alguns subshells, não em todos os subshells.Antes de afirmar que o subprocesso em que um comando de pipeline é executado não é um subshell realmente real, considere este
man bash
trecho:e as implicações práticas -- é se um fragmento de script é executado em um subprocesso ou não o que é essencial, e não algum problema de terminologia.
A única solução, como já explicado nas respostas a esta pergunta, é verificar se
$BASHPID
é igual$$
ou, portátil, mas muito menos eficiente: