Perl - 终止从管道启动的正在进行的进程

标签 perl pipe kill iostat

我的目标是启动一个正在进行的进程(例如 iostat)并解析一些信息。完成后,我想杀死 iostat 并优雅地关闭管道。请记住,iostat 将永远运行,直到我杀死它。

如果我尝试在关闭管道之前终止进程,close() 将返回 -1,表示“无子进程”。如果我在关闭管道之前没有终止进程,它会返回 13,因为 iostat 仍在尝试写入我的管道。换句话说,这个脚本总是会die()。

如何优雅地关闭这个管道?

use warnings;
use strict;

my $cmd = "iostat 1";
my $pid = open(my $pipe, "$cmd |") || die "ERROR: Cannot open pipe to iostat process: $!\n";
my $count = 0;

while (<$pipe>){
  if ($count > 2){ 
    kill(9, $pid);    # if I execute these two lines, close() returns -1
    waitpid($pid, 0); # otherwise it returns 13
    last;
  }
  $count++;
}
close($pipe) || die "ERROR: Cannot close pipe to iostat process: $! $?\n";
exit 0;

最佳答案

要理解为什么会发生这种情况,您需要了解关闭此类管道时 Perl 幕后发生的情况。

另请参阅 close 的描述在 perldoc 上它说

If the filehandle came from a piped open, close returns false if one of the other syscalls involved fails or if its program exits with non-zero status.

实际关闭底层文件描述符后,perl 调用系统调用“waitpid()”来收集进程(如果它不这样做,您手上就会有一个“僵尸”进程)。如果进程已经退出,则 waitpid 返回错误代码 ECHILD,“无子进程”。这是 perl 从 close 函数报告的错误代码。

您可以通过从循环内部删除“waitpid”调用来避免这种情况,以便 Perl 在您关闭管道时可以执行此操作。不过,您仍然会收到错误,因为被终止进程的返回码由终止进程的信号号组成,或者由实际返回码左移 8 位组成。你可以通过检查 $! 来处理这个问题。 == 0 和 $? == 9(或您使用的任何信号编号)。

所以你的代码可能如下所示:

use warnings;
use strict;

my $cmd = "iostat 1";
my $pid = open(my $pipe, "$cmd |") || die "ERROR: Cannot open pipe to iostat process: $!\n";
my $count = 0;

while (<$pipe>){
  if ($count > 2){
    kill(9, $pid);    # if I execute these two lines, close() returns -1
    last;
  }
  $count++;
}
unless (close($pipe)) {
        die "ERROR: Cannot close pipe to iostat process: $! $?\n" if $! != 0 || $? != 9;
}
exit 0;

关于Perl - 终止从管道启动的正在进行的进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20084898/

相关文章:

perl - 如果我有 t 统计量和 d.f.,我如何计算 p 值? (在 Perl 中)?

ios - dyld:未加载库:libperl.dylib 引用自:perl5.18

c - 用 C 编写自己的 shell - 如何制作两个以上的管道?

在 Windows 上通过管道进行 Java/C++ 通信

java - 查找谁(什么)杀死了我的进程

java - GC 暂停和 kill -STOP 会产生相同的行为吗?

perl - -B 文件测试的可靠性如何?

c - 管道系统调用

c++ - 与 parent 一起杀死qprocess

perl - 无法使用 $|=1 关闭 Perl 中的缓冲;