Eu nunca pensei sobre como o shell realmente executa comandos canalizados. Sempre me disseram que o "stdout de um programa é canalizado para o stdin de outro", como uma maneira de pensar sobre os pipes. Então, naturalmente, pensei que, no caso de dizer, A | B, A seria executado primeiro, depois B obtém o desvio padrão de A e usa o desvio padrão de A como entrada.
Mas notei que quando as pessoas pesquisam um processo específico no ps, elas incluem grep -v "grep" no final do comando para garantir que o grep não apareça na saída final. Isso significa que no comando ps aux | grep "bash" | grep -v "grep", o que significa que o ps sabia que o grep estava em execução e, portanto, está na saída do ps. Mas se o ps terminar de executar antes que sua saída seja canalizada para grep, como ele sabia que o grep estava em execução?
flamingtoast@FTOAST-UBUNTU: ~$ ps | grep ".*"
PID TTY TIME CMD
3773 pts/0 00:00:00 bash
3784 pts/0 00:00:00 ps
3785 pts/0 00:00:00 grep
Respostas:
Os comandos canalizados são executados simultaneamente. Quando você corre
ps | grep …
, é a sorte do empate (ou uma questão de detalhes do funcionamento do shell, combinada com o agendador que afina profundamente as entranhas do kernel) sobre se deveps
ougrep
começa primeiro e, em qualquer caso, eles continuam a executar simultaneamente.Isso é muito comumente usado para permitir que o segundo programa processe dados à medida que saem do primeiro programa, antes que o primeiro programa tenha concluído sua operação. Por exemplo
começa a exibir as linhas correspondentes em maiúsculas mesmo antes de
grep
terminar de atravessar o arquivo grande.exibe a primeira linha correspondente e pode parar o processamento bem antes de
grep
terminar de ler seu arquivo de entrada.Se você ler em algum lugar que os programas canalizados sejam executados em sequência, fuja deste documento. Programas canalizados são executados simultaneamente e sempre foram executados.
fonte
grep
programa e existe um buffer gerenciado pelo kernel no próprio pipe. Para o último, consulte Qual é o tamanho do buffer do pipe?A ordem em que os comandos são executados não importa e não é garantida. Deixando de lado os detalhes secretos de
pipe()
,fork()
,dup()
eexecve()
, a concha primeiro cria o tubo, a conduta para o fluxo de dados que vai entre os processos, e, em seguida, cria os processos com as extremidades do tubo ligado a eles. O primeiro processo executado pode bloquear a espera pela entrada do segundo processo ou bloquear a espera pelo segundo processo para começar a ler dados do canal. Essas esperas podem ser arbitrariamente longas e não importam. Qualquer que seja a ordem em que os processos são executados, os dados são transferidos e tudo funciona.fonte
Correndo o risco de bater em um cavalo morto, o equívoco parece ser que
é equivalente a
Porém, quando o Unix foi criado e as crianças levavam dinossauros para a escola, os discos eram muito pequenos e era comum um comando bastante benigno consumir todo o espaço livre em um sistema de arquivos. Se
B
fosse algo assim , a saída final do pipeline poderia ser muito menor que o arquivo intermediário. Portanto, o tubo foi desenvolvido, não como uma abreviação para a “executar Um primeiro, e em seguida, executar B com a entrada de um ‘s saída”modelo, mas como uma forma para executar concorrentemente com e eliminar a necessidade de armazenar o ficheiro intermédio no disco.grep some_very_obscure_string
B
A
fonte
Normalmente, você executa isso no bash. processo funcionando e iniciando simultaneamente, mas está sendo executado pelo shell em paralelo. Como isso é possível?
O sistema não garante a rapidez com que o exec será executado e o comando especificado será iniciado. é independente do shell, mas do sistema. Isto é porque:
uma vez mostre
grep
e / oups
comando, e depois agora. Depende de quão rápido o kernel realmente inicia os processos usando a função exec do sistema.fonte
exec()
é executado, mas como asexec()
chamadas e a execução dos programas em um canal são intercaladas .