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

Mor*_*itz 3 perl perl-io perl-ipc-run

我必须杀死我正在通过的程序

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

或者

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

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

有没有办法让程序真正的PID?获取shPID 的意义何在?

zdi*_*dim 8

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

首先,你可以使用一个列表的形式打开一个过程,然后没有shell参与这样子进程(将其中的pid返回open)恰恰是一个与你需要停止程序

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

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

...

my $num_signaled = kill 15, $pid;
Run Code Online (Sandbox Code Playgroud)

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

如果由于某种原因这不合适——也许你需要shell 来运行那个程序——那么你可以找到程序的 pid,而Proc::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;
Run Code Online (Sandbox Code Playgroud)

请小心通过名称识别程序——在现代系统上,可能会运行各种包含您要终止的程序名称的进程。有关更多详细信息和讨论,请参阅这篇文章这篇文章,作为初学者。

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

  • 请注意,使用列表形式并不能保证 Windows 中没有 shell。 (2认同)