De acordo com isso , a colocação de uma lista de comandos entre chaves faz com que a lista seja executada no contexto atual do shell. Nenhum subshell é criado .
Usando ps
para ver isso em ação
Esta é a hierarquia de processos para um pipeline de processos executado diretamente na linha de comandos. 4398 é o PID para o shell de login:
sleep 2 | ps -H;
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29696 pts/23 00:00:00 sleep
29697 pts/23 00:00:00 ps
Agora segue a hierarquia do processo para um pipeline de processo entre chaves executadas diretamente na linha de comando. 4398 é o PID para o shell de logon. É semelhante à hierarquia acima, provando que tudo é executado no contexto atual do shell :
{ sleep 2 | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29588 pts/23 00:00:00 sleep
29589 pts/23 00:00:00 ps
Agora, essa é a hierarquia do processo quando o sleep
próprio pipeline é colocado dentro de chaves (portanto, dois níveis de chaves)
{ { sleep 2; } | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29869 pts/23 00:00:00 bash
29871 pts/23 00:00:00 sleep
29870 pts/23 00:00:00 ps
Por que é bash
necessário criar um subshell para execução sleep
no terceiro caso, quando a documentação declara que os comandos entre chaves são executados no contexto atual do shell?
{ sleep 2 | command ps -H; }
Respostas:
Em um pipeline, todos os comandos são executados simultaneamente (com seus stdout / stdin conectados por pipes), portanto, em diferentes processos.
Em
Todos os três comandos são executados em processos diferentes, portanto, pelo menos dois deles precisam ser executados em um processo filho. Alguns shells executam um deles no processo atual do shell (se embutido como
read
ou se o pipeline é o último comando do script), masbash
executa todos eles em seu próprio processo separado (exceto com alastpipe
opção nasbash
versões recentes e sob algumas condições específicas ){...}
agrupa comandos. Se esse grupo fizer parte de um pipeline, ele deverá ser executado em um processo separado, como um simples comando.Em:
Precisamos de um shell para avaliar que
a; b "$?"
é um processo separado, por isso precisamos de um subshell. O shell pode otimizar não sendo bifurcado,b
já que é o último comando a ser executado nesse grupo. Algumas conchas fazem isso, mas aparentemente nãobash
.fonte
bash -c "sleep 112345 | cat | cat "
vejo apenas uma festança criada e, em seguida, três filhos sem nenhuma outra festança secundária.a; b "$?"
? Existe realmente uma necessidade fundamental de um subsheel, ou talvez seja uma decisão / implementação de projeto no bash?eval
), mas a avaliação (execute o primeiro comando, aguarde, execute o segundo) é feito na criança, aquela que está desconectada do tubo.{ sleep 2 | ps -H; }
bash pai vêsleep 2
que requer um fork / exec. Mas no{ { sleep 2; } | ps -H; }
bash pai vê{ sleep 2; }
em outras palavras, algum código bash. Parece que o pai pode manipular o fork / exec,sleep 2
mas gera um novo bash recursivamente para manipular o código do bash encontrado. Esse é o meu entendimento, isso faz sentido?Aninhar os chavetas parece indicar que você está criando um nível adicional de escopo, que exige que uma nova subcasca seja invocada. Você pode ver esse efeito com a segunda cópia do Bash em sua
ps -H
saída.Somente os processos estipulados no primeiro nível de chaves são executados no escopo do shell Bash original. Qualquer aparelho cacheado aninhado será executado em seu próprio shell Bash com escopo.
Exemplo
Retirando a
| ps -H
mistura apenas para que possamos ver as chaves aninhadas, podemos executarps auxf | less
em outro shell.Mas espere, tem mais!
Se você remover os pipes e usar esta forma de comando, veremos o que você realmente espera:
Agora, na janela de inspeção resultante, temos uma atualização a cada 2 segundos do que está acontecendo:
Aqui está o primeiro
sleep 10
:Aqui está o segundo
sleep 10
:Aqui está o terceiro
sleep 10
:Observe que todos os três dormes, embora invocados em diferentes níveis de aninhamento de chaves, permanecem dentro do PID 5676 do Bash. Portanto, acredito que seu problema é auto-infligido com o uso de
| ps -H
.Conclusões
O uso de
| ps -H
(ou seja, o tubo) está causando uma subcama adicional, portanto, não use esse método ao tentar interrogar o que está acontecendo.fonte
Vou postar os resultados dos meus testes, o que me leva a concluir que o bash cria um sub-shell para um comando de grupo se, e somente se for parte do pipeline, é semelhante como se alguém chamasse alguma função que também seria chamada no sub-shell.
fonte