Um sub-shell é a mesma coisa que um sub-shell

11

Existem esses dois nomes: um subshell e um shell filho .

Sim, um processo filho será iniciado por qualquer um destes:

sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat

Todos são equivalentes e compartilham o mesmo nome? Todos compartilham as mesmas propriedades?


O POSIX possui esta definição :

Um ambiente de execução de shell consiste em ....

Mas o último parágrafo do link acima tem o seguinte:

Um ambiente de subcasca deve ser criado como uma duplicata do ambiente de shell, exceto que os traps de sinal que não estão sendo ignorados devem ser configurados para a ação padrão.

E especialmente:

A substituição de comandos, os comandos agrupados entre parênteses e as listas assíncronas devem ser executadas em um ambiente de subcasca. Além disso, cada comando de um pipeline de comandos múltiplos está em um ambiente de subcasca; ....

O sh -c 'echo "Hello"'não está incluído lá, isso também deve ser chamado de subshell?

Gilles 'SO- parar de ser mau'
fonte

Respostas:

14

Um subshell duplica o shell existente. Possui as mesmas variáveis¹, as mesmas funções, as mesmas opções, etc. Sob o capô, um subshell é criado com a forkchamada do sistema²; o processo filho continua fazendo o que é esperado dele enquanto o pai espera (por exemplo $(…)) ou continua sua vida (por exemplo … &) ou faz o que é esperado dele (por exemplo … | …).

sh -c …não cria um subshell. Lança outro programa. Esse programa passa a ser um shell, mas isso é apenas uma coincidência. O programa pode até ser um shell diferente (por exemplo, se você executar a sh -c …partir do bash e shfor um dash), ou seja, um programa completamente diferente que, por acaso, possui semelhanças significativas em seu comportamento. Sob o capô, o lançamento de um comando externo ( shou qualquer outro) chama a chamada do forksistema e, em seguida, a execvechamada do sistema para substituir o programa shell no subprocesso por outro programa (aqui sh).

¹ Incluindo $$, mas excluindo algumas variáveis ​​específicas do shell, como bash e mksh's BASHPID.
² Pelo menos, essa é a implementação tradicional e usual. Os reservatórios podem otimizar o garfo, caso possam imitar o comportamento.

Páginas de manual relevantes: fork (2) , execve (2) .

Gilles 'SO- parar de ser mau'
fonte
Obrigado. A que pertence a execução de um script bash com bash shebang?
Tim
@ Tim A mesma coisa que sh -c: esse é um subprocesso que por coincidência é um shell.
Gilles 'SO- stop be evil'
(1) "iniciar um comando externo (sh ou qualquer outro) chama a chamada do sistema fork e, em seguida, a chamada do sistema execve para substituir o programa shell no subprocesso por outro programa (aqui sh)." É certo que o fork garanta primeiro um subshell e, em seguida, execute a substituição do subshell pelo programa externo? Portanto, nos dois casos da sua resposta, sempre é criado um subshell? (2) "Um subshell que duplica o shell existente." o que isso significa?
Tim
(3) bash -c <command>, depois de bifurcar o shell e, em seguida bash -c <command>, executar , um shell bash é criado. Então, a chamada do sistema usada para executar <command>novamente bifurca o shell bash e executa <command>?
Tim
2
@cuonglm “shell filho” não é um termo técnico com um significado específico, ao contrário de “subshell”. Se é um shell filho, é um shell filho, seguindo as regras usuais do inglês.
Gilles 'SO- stop be evil'
1

Um ambiente de subcasca não precisa viver em um processo separado, apenas duplicar o ambiente de execução atual. Em ksh93isso é feito por um virtual sub-shellmecanismo que não chama fork(). Isso torna o ksh93 muito rápido em plataformas arcaicas Win-DOS, como Win-DOSé extremamente lento com o bifurcação.

sh -c cmd por outro lado, cria um novo processo com o shell padrão que não precisa ser igual ao seu shell interativo atual.

Mesmo quando she seu shell atual são idênticos, isso não duplica o ambiente de execução e, portanto, não cria um sub-shell.

esperto
fonte
Então, em outras conchas ksh93, exceto , subshell é um shell filho, certo?
cuonglm
Não conheço outra implementação que implemente subshells virtuais hoje.
schily