我正在使用 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
死亡。
program1
SIGPIPE
当管道断开时会收到信号。设计为长期运行守护进程的程序通常会处理信号并进行适当的清理,但典型的交互式程序不会这样做。默认操作是终止程序,因此在大多数情况下,program1
只会被终止。