Quando a entrada da tubulação de um programa para outro, o que acontece com o programa original se a saída de recepção do programa é eliminada?

1

Estou canalizando a saída de um programa como este usando o bash:

program1 | program2

Se o programa2 é morto de alguma forma (no meu caso por um erro fatal do PHP), o que acontece com a instância do programa1?

    
por Max 27.04.2011 / 14:04

4 respostas

3

Depende muito de qual program1 é. O software precisa ser capaz de manipular (ou ignorar) um sinal SIGPIPE . program1 será responsável por lidar com o erro - se o software for de código aberto, você deve ser capaz de discernir o que acontece ou se ele captura / detecta um sinal SIGPIPE . Se o software não fizer nada de especial com fluxos, provavelmente concluirá a execução antes de transmitir os resultados. Eu tentei um pequeno exemplo para mostrar o ponto usando dois scripts php.

program1

#!/usr/bin/env php
<?php

@unlink('program1.out');

for( $i = 0; $i < 10; $i++ )
{
    // This goes to either the buffer or whoever is next in the pipe
    echo $i . PHP_EOL;
    // Put everything in a file so we can see what Program1 actually did
    file_put_contents('program1.out', $i . PHP_EOL, FILE_APPEND);   
}

// All done! Cap off the file
file_put_contents('program1.out', 'Fin', FILE_APPEND);

program2

#!/usr/bin/env php
<?php

// We're taking inputs and just redirecting them to program2.out
// but to make it fun I'll throw an error half way through
// because I'm malicious like that

@unlink('program2.out');

$pipe_input = file("php://stdin");
$pipe_total = count($pipe_input);
$stop = rand(0, $pipe_total - 1);

echo "I'll be stopping at $stop" . PHP_EOL;

foreach( $pipe_input as $key => $input )
{
    if( $key == $stop )
    {
        file_put_contents('program2.out', 'Dead!', FILE_APPEND);
        die(1);
    }

    file_put_contents('program2.out', $input, FILE_APPEND);
}

Quando você executar ./program1 | ./program2 , obterá dois arquivos .out , um para cada programa. No exemplo que eu executei, eu peguei os seguintes arquivos:

0
1
2
3
4
5
6
7
8
9
Fin

E para program2.out

0
1
2
3
4
Dead!

O primeiro programa executará e passará seu conteúdo para o segundo. Você notará que o arquivo .out do primeiro programa tem um conjunto completo de números e o segundo contém apenas um conjunto disso porque foi anulado.

    
por Marco Ceppi 27.04.2011 / 14:28
1

O tubo será quebrado e o programa gravando no tubo receberá um sinal SIGPIPE.

De GLIBC :

  

SIGPIPE       Cano quebrado. Se você usa canos ou FIFOs, você tem que projetar seu   aplicação de modo que um processo é aberto   o tubo para ler antes de outro   começa a escrever. Se o processo de leitura   nunca começa, ou termina   inesperadamente , escrevendo no pipe ou   FIFO gera um sinal SIGPIPE. E se   SIGPIPE é bloqueado, manipulado ou   ignorada, a chamada incorreta falha com   EPIPE em vez disso.

    
por Egil 27.04.2011 / 14:17
0

Nada. Os dados vão para / dev / null. P.S. Ah, sim, o programa vai receber um sinal, mas isso não significa que terá que fechar.

    
por Barafu Albino 27.04.2011 / 14:10
0

A resposta curta é que program1 morre.

program1 recebe um sinal SIGPIPE quando o tubo está quebrado. Programas projetados para serem daemons de longa duração normalmente lidam com o sinal e fazem uma limpeza adequada, mas o seu programa interativo típico não. A ação padrão é terminar o programa, então, na maior parte, program1 será terminado.

    
por psusi 27.04.2011 / 15:47