perl open() 总是返回 sh 的 PID 而不是底层程序

标签 perl perl-io perl-ipc-run

我必须终止通过

打开的程序

$pid = open(FH, "program|")

$pid = or open(FH, "-|", "program")

但是,该程序(具体来说是 mosquittto_sub)仍然在后台徘徊,因为 open 正在返回 perl 用来运行的 sh 的 PID程序,所以我只杀死 sh 包装器而不是实际程序。

有没有办法让程序获得真正的 PID?获取 sh 的 PID 有什么意义?

最佳答案

有几种方法可以解决这个问题。

首先,您可以使用列表形式open一个进程,然后不涉及shell,因此子进程(由open返回的pid) 正是你需要停止的那个程序

my @cmd = ('progname', '-arg1', ...);

my $pid = open my $fh, '-|', @cmd  // die "Can't open \"@cmd\": $!";

...

my $num_signaled = kill 15, $pid;

此草图需要添加一些检查。请参阅链接文档(查找“管道”)。

如果由于某种原因这不适合 - 也许您需要 shell 来运行该程序 - 那么您可以找到程序的 pidProc::ProcessTable 模块对此有好处。一个基本的演示

use Proc::ProcessTable;

my $prog_name = ...

my $pid;
my $pt = Proc::ProcessTable->new();

foreach my $proc (@{$pt->table}) {
    if ($proc->cmndline =~ /\Q$prog_name/) {  # is this enough to identify it?
        $pid = $proc->pid;
        last;
    }   
}
my $num_signaled = kill 15, $pid;

请注意通过名称来识别程序——在现代系统上,可能有各种正在运行的进程包含您要终止的程序的名称。有关更多详细信息和讨论,请参阅 this postthis post ,供初学者引用。

最后,您可以使用一个模块来运行您的外部程序,然后您就可以更好地管理和控制它们。这里我推荐 IPC::Run

关于perl open() 总是返回 sh 的 PID 而不是底层程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60272757/

相关文章:

perl - 使用 Perl 的 Net::SSLeay 获取整个证书

perl - 使用 homebrew 升级 Perl 版本时如何最好地处理以前安装的模块

perl - 您是否将 Perl 应用程序开发为 CPAN 模块?

utf-8 - 在 Perl 中使用带有标量和 I/O 层的 open() 时编码的不确定性

perl - 使用 Perl XS 和 PerlIO 使旧库工作

perl - 如何判断 IPC::Run 作业何时完成

perl - Perl 中的波浪号 (~) 目录