Os utilitários do Linux são inteligentes ao executar comandos canalizados?

23

Eu estava apenas executando alguns comandos em um terminal e comecei a pensar: o Unix / Linux usa atalhos ao executar comandos canalizados?

Por exemplo, digamos que eu tenha um arquivo com um milhão de linhas, as 10 primeiras contendo hello world. Se você executar o comando grep "hello world" file | head, o primeiro comando será interrompido assim que encontrar 10 linhas ou continuará pesquisando primeiro o arquivo inteiro?

DisgruntledGoat
fonte
2
É por isso que o gnu grep tem o -margumento.
Paul Tomblin
3
O terminal não tem nada a ver com isso. Os comandos canalizados são gerenciados pelo shell.
Keith Thompson
@KeithThompson perdoe minha ignorância, eu não sou grande em terminologia, não tinha certeza se deveria chamá-lo de terminal, shell ou linha de comando. Sinta-se livre para sugerir edições à minha pergunta :) #
DisgruntledGoat

Respostas:

30

Tipo de. O shell não tem idéia do que os comandos que você está executando farão, apenas conecta a saída de um à entrada do outro.

Se grepencontrar mais de 10 linhas que dizem "olá mundo", headterá todas as 10 linhas que deseja e feche o tubo. Isso fará com grepque seja morto com um SIGPIPE, portanto, não é necessário continuar a varredura de um arquivo muito grande.

psusi
fonte
2
Então eu acho que, devido às condições da corrida, o grep pode já ter lido o 11º ou o 12º padrão, mas provavelmente não os 100 mil?
usuário desconhecido
3
Isso depende em parte do comprimento das linhas e do tamanho do buffer do pipe, mas a resposta curta é que o grep lerá uma quantidade razoavelmente limitada de dados extras antes de ser eliminado.
dmckee
1
@userunknown, exatamente.
Psusi
Legal, eu não sabia o que tinha acontecido. Eu pensei grepque continuaria enviando saída para um vazio, semelhante a/dev/null
Izkata
15

Quando um programa tenta gravar em um canal e não há leitura de processo nesse canal, o programa gravador recebe um sinal SIGPIPE . A ação padrão quando um programa recebe o SIGPIPE é finalizar o programa. Um programa pode optar por ignorar o sinal SIGPIPE; nesse caso, a gravação retorna um erro ( EPIPE).

No seu exemplo, aqui está uma linha do tempo do que acontece:

  • Os comandos grepe headsão iniciados em paralelo.
  • grep lê alguma entrada, começa a processá-la.
  • Em algum momento, grepproduz um primeiro pedaço de saída.
  • head lê esse primeiro pedaço e escreve.
  • Supondo que haja linhas suficientes após as 10 primeiras correspondências (caso contrário, greppode terminar primeiro), eventualmente, headserá impresso o número desejado de linhas. Neste ponto, headsai.
  • Dependendo da velocidade relativa dos processos grepe head, greppode ter acumulado alguns dados e ainda não os impresso. No momento da headsaída, greppode estar lendo a entrada ou fazendo um processamento interno; nesse caso, continuará a fazê-lo.
  • Em grepbreve gravará os dados processados. Nesse ponto, ele receberá um SIGPIPE e morrerá.

É provável que grepprocesse um pouco mais do que o estritamente necessário, mas geralmente apenas alguns kilobytes:

  • headnormalmente lê em pedaços de alguns kilobytes (porque é mais eficiente do que emitir uma readchamada do sistema para cada byte - esse comportamento é chamado de buffer), portanto, o restante do último pedaço após a última linha desejada é descartado.
  • Pode haver alguns dados em trânsito, pois os pipes têm um buffer associado gerenciado pelo kernel (geralmente 512 bytes). Esses dados serão descartados.
  • greppode ter acumulado alguns dados prontos para se tornar um pedaço de saída (buffer novamente). Ele receberá o SIGPIPE quando estiver tentando liberar seu buffer de saída.

Em suma, o sistema foi projetado com precisão para que os utilitários de filtragem se comportem naturalmente com eficiência. Os programas que precisam continuar quando o canal de saída desaparece devem ignorar o sinal SIGPIPE.

Gilles 'SO- parar de ser mau'
fonte
3

No entanto, o pipeline funciona assim: primeiro executa o primeiro comando e depois o segundo comando no seu caso.

Ou seja, vamos ter A|Bo comando dado. Então é incerto se Aou Bcomeça primeiro. Eles podem começar exatamente ao mesmo tempo se houver várias CPUs. Um canal pode conter uma quantidade indefinida, mas finita, de dados.

Se B tentar ler do canal, mas nenhum dado estiver disponível, Besperará até que os dados cheguem. Se Bestava lendo um disco, Bpode ter o mesmo problema e precisar aguardar até que a leitura do disco termine. Uma analogia mais próxima seria a leitura de um teclado. Lá, Bseria necessário aguardar o usuário digitar. Mas em todos esses casos, B iniciou uma operação de "leitura" e deve esperar até que seja concluída. Mas se Bé um comando que precisa apenas de saída parcial A, após certo ponto em que Bo nível de entrada é atingido Aserá eliminado pelo SIGPIPE

Se Atentar gravar no tubo e o tubo estiver cheio, Aespere que haja espaço no tubo livre. Apoderia ter o mesmo problema se estivesse gravando em um terminal. Um terminal possui controle de fluxo e pode moderar o ritmo dos dados. De qualquer forma, para A, iniciou uma operação de "gravação" e aguardará até que a operação de gravação seja concluída.

Ae Bestão se comportando como co-processos, embora nem todos os co-processos se comuniquem com um canal. Nenhum deles está no controle total do outro.

harish.venkat
fonte
1
A pergunta é: "o que faria A quando B fechar o lado do tubo?"
enzotib
2
Isso não seria um "cano quebrado"?
Patkos Csaba
1
Se um programa tentar ler / gravar de / para um tubo fechado (por exemplo, headsaídas), um sinal SIGPIPE ocorre no programa e o comportamento padrão é sair.
Lekensteyn
Como exatamente isso responde à pergunta? Parece que a resposta de psusi é mais curta e mais objetiva .
Jw013
1

grepnão tem controle direto do canal (está apenas recebendo dados) e o canal não tem controle direto grep(está apenas enviando dados) ...

O que grep, ou qualquer outro programa faz, depende inteiramente da lógica interna do programa. Se você disser, greppor meio das opções da linha de comando, para fazer uma saída antecipada quando encontrada , será o caso, caso contrário, será executado no final do arquivo procurando o padrão ...

O terminal também está bastante desconectado do funcionamento interno grepe das shellações da tubulação ... O terminal é basicamente apenas uma plataforma de lançamento e exibição de saída ...

Peter.O
fonte