É bem sabido que ao executar bash -c "COMMAND"
(pelo menos nas versões comuns do Linux) quando há um único comando sem nenhum metacaractere (exceto space , tab ou newline ), o bash -c
processo não irá bifurcar, mas sim substituir-se executando COMMAND
diretamente com execve
a chamada do sistema para otimização, então o resultado será apenas um processo.
$ pid=$$; bash -c "pstree -p $pid"
bash(5285)───pstree(14314)
Se houver algum metacaractere (como redirecionamento) ou mais de um comando (que requer um metacaractere de qualquer maneira), bash
será bifurcado para cada comando executado.
$ pid=$$; bash -c ":; pstree -p $pid"
bash(5285)───bash(28769)───pstree(28770)
$ pid=$$; bash -c "pstree -p $pid 2>/dev/null"
bash(5285)───bash(14403)───pstree(14404)
Este é um recurso de otimização não documentado (o que significa que não é garantido) ou está documentado em algum lugar e garantido?
Nota: Presumo que nem todas as versões bash
se comportem assim e que em algumas versões que o fazem, é apenas considerado um detalhe de implementação e não garantido, mas gostaria de saber se talvez existam pelo menos algumas bash
versões que suportem explicitamente isso e documentem a condição por esta. Por exemplo, se houver um único ;
caractere após o comando, sem nenhum segundo comando, bash
ainda execve
não haverá bifurcação.
$ pid=$$; bash -c "pstree -p $pid ; "
bash(17516)───pstree(17658)
Antecedentes da minha pergunta
Como mencionei, esse comportamento é bastante conhecido 1 2 por bash
usuários experientes e estou familiarizado com ele há muito tempo.
Alguns dias atrás, encontrei o seguinte comentário no shell bash interativo: Defina o diretório de trabalho por meio de opções de linha de comando onde @dave_thompson_085 escreveu:
bash
executa automaticamente (ou seja, substitui-se por) o último (ou único) comando em-c
.
Eu respondi que isso só é verdade se houver um único comando. Mas então me perguntei: existem algumas versões em bash
que talvez o último comando seja exec
ed e não bifurcado, mesmo que haja outro comando antes dele? E em geral, há casos em que esse comportamento é garantido? Certas bash
versões expõem (e elaboram) esse recurso fora do código-fonte?
O uso
exec
é um detalhe de implementação - se não estiver documentado, o comportamento não será garantido em nenhuma versão. Talvez seja útil explicar um pouco por que tendemos a não documentar esse tipo de coisa com base na minha experiência no desenvolvimento de outro software amplamente utilizado (o kernel Linux).Em geral, para qualquer software amplamente utilizado, geralmente tenta-se descrever apenas os recursos, a operação e os comportamentos padrão. Normalmente evita-se aprofundar as especificidades das otimizações internas por medo de criar dependências posteriores nesse comportamento.
Como um exemplo da minha própria área de trabalho, trabalho no gerenciamento de memória do kernel e não procuramos documentar detalhadamente (por exemplo) exatamente como funcionam os internos de priorização de recuperação ou exatamente quando coisas como a verificação de LRU são executadas. Documentar isso tornaria as decisões futuras sobre otimizações e outras mudanças muito mais complicadas de serem tomadas, porque agora temos que considerar se estamos quebrando alguma dependência downstream intangível e desconhecida.
Da mesma forma, no caso do bash ou de qualquer outro sistema de software complexo, mecanismos internos como a decisão de usar
exec
em vez de bifurcar um novo processo podem estar sujeitos a alterações, mesmo com um aviso muito curto. Imagine se houver novas otimizações de desempenho, considerações de segurança ou problemas de compatibilidade que exijam o não uso repentino do exec. Queremos realmente estar vinculados por contrato para continuar a operar dessa forma? Claro que não.No bash, e na maioria dos outros projetos amplamente utilizados, há uma forte ênfase na manutenção de uma interface externa estável e bem definida que contenha apenas as coisas consideradas necessárias para serem expostas, permitindo que a implementação interna evolua conforme necessário. Esta abordagem garante que o software permaneça robusto, seguro e eficiente, sem sacrificar a capacidade de inovar e melhorar.
Então, para responder à sua pergunta, não, isso não está documentado e você não deve confiar nisso. Também é altamente improvável que este ou outros casos semelhantes sejam documentados, porque adicionar restrições internas tornaria o desenvolvimento muito mais rígido.