当将输入从一个程序传输到另一个程序时,如果接收输出的程序被终止,原始程序会发生什么?

当将输入从一个程序传输到另一个程序时,如果接收输出的程序被终止,原始程序会发生什么?

我正在使用 bash 传输如下程序的输出:

program1 | program2

如果 program2 因某种原因被终止(在我的情况下是由于 PHP 致命错误),那么 program1 的实例会发生什么?

答案1

这很大程度上取决于program1是什么。软件需要能够处理(或忽略)SIGPIPE信号。program1将负责处理错误 - 如果软件是开源的,您应该能够辨别发生了什么,或者它是否捕获/检测到信号SIGPIPE。如果软件没有对流进行任何特殊处理,它可能会先完成执行,然后再传递结果。我尝试了一个使用两个 php 脚本的小例子来说明这一点。

程序1

#!/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);

程序2

#!/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);
}

执行后,./program1 | ./program2您将获得两个.out文件,每个程序一个。在我运行的示例中,我获得了以下文件:

0
1
2
3
4
5
6
7
8
9
Fin

对于program2.out

0
1
2
3
4
Dead!

第一个程序将执行并将其内容传递给第二个程序。您会注意到第一个程序的 .out 文件包含一组完整的数字,而第二个程序只包含一组数字,因为它已被终止。

答案2

管道将被断开,并且写入管道的程序将收到 SIGPIPE 信号。

类库

SIGPIPE 管道损坏。如果您使用管道或 FIFO,则必须设计应用程序,以便一个进程在另一个进程开始写入之前打开管道进行读取。如果读取过程从未启动,或意外终止,写入管道或 FIFO 会引发 SIGPIPE 信号。如果 SIGPIPE 被阻止、处理或忽略,则有问题的调用会失败并产生 EPIPE。

答案3

没什么。数据进入 /dev/null。PS 哦,是的,程序将收到信号,但这并不意味着它必须关闭。

答案4

简短的回答就是program1死亡。

program1SIGPIPE当管道断开时会收到信号。设计为长期运行守护进程的程序通常会处理信号并进行适当的清理,但典型的交互式程序不会这样做。默认操作是终止程序,因此在大多数情况下,program1只会被终止。

相关内容