【问题标题】:perl open() always returns the PID of the sh instead of the underlying programperl open() 总是返回 sh 的 PID 而不是底层程序
【发布时间】:2020-06-01 23:51:09
【问题描述】:

我必须杀死一个我通过

打开的程序

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

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

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

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

【问题讨论】:

  • 您是在pid 上使用kill 还是在FH 上使用close
  • kill on $pid,因为子程序在关闭时挂起/阻塞。所以我必须手动杀死它,而不是仅仅调用close

标签: perl perl-io perl-ipc-run


【解决方案1】:

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

首先,您可以使用列表形式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 来运行那个程序——那么你可以找到程序的 pid,然后@987654322 @ 模块对此有好处。一个基本的演示

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

【讨论】:

  • 请注意,使用列表形式并不能保证在 Windows 中没有 shell。
  • 我采用了 command-args-as-list 方法,效果很好。还解释了为什么open() 调用sh - 来处理命令行参数处理。
猜你喜欢
  • 1970-01-01
  • 2015-07-06
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多