我有一些像这样的perl代码来获取进程的pid(如果它) 存在。我想知道 pgrep 的返回状态,这样我就可以知道 pid 是否有效。这是代码:
#!/usr/bin/perl -w
my $pid=`pgrep -n -f \"akonadiserver\"`;
print "$? ";
chomp $pid;
print "Output1: $pid\n";
$pid=`pgrep -n -f \"akonadiserver\"`;
my $evalue=${^CHILD_ERROR_NATIVE};
chomp $pid;
print "Output2: $pid, $evalue\n";
但是每当我运行它时,我都会得到以下信息:
0 Output1: 3054
Output2: 3056, 0
再跑一次
0 Output1: 3059
Output2: 3061, 0
但是在系统中:
$ pgrep -n -f akonadiserver
1862
这里看到的几个问题:
1) 返回的 pid 一直在变化,很可能是匹配的 grep 进程本身。
2) 我没有办法确定返回的 pid 是否有效。 $?
没有帮助。
如何检查返回状态以及如何在 Perl 中正确使用 pgrep?
最佳答案
从 Perl 脚本运行 `pgrep -n -f akonadiserver`
相当于从终端运行 sh -c "pgrep -n -f akonadiserver"
。
来自perlop
:
qx/STRING/:
A string which is (possibly) interpolated and then executed as a system command with /bin/sh or its equivalent.
问题在于,将 -f
选项与 pgrep
一起使用将与用于调用该进程的完整命令行进行匹配。这还将包括当前的 pgrep
命令,因为它的命令行将类似于 sh -c "pgrep -n -f akonadiserver"
,它将与字符串 "匹配akonadiserver”
。由于您还将 -n
标志与 pgrep
一起使用,因此它只会返回与 "akonadiserver"
匹配的最新进程,这很可能是pgrep
命令本身(sh -c "pgrep -n -f akonadiserver"
).. 这解释了为什么你得到错误的进程 ID。
但是它没有解释为什么它仍然可以在终端窗口中运行。原因是在终端窗口中,pgrep
命令是使用 bash
而不是 sh
运行的(与 Perl 脚本一样),请参阅此有关差异的更多信息,请询问:Difference between pgrep in sh and bash 。因此,从终端窗口运行 pgrep -f
将不会包含 pgrep
命令本身,因此它将适合您的情况。
要从 Perl 获得可靠的结果,您应该使用 Proc::ProcessTable
:
use feature qw(say);
use strict;
use warnings;
use Proc::ProcessTable;
my $pat = "akonadiserver";
my $pt = Proc::ProcessTable->new();
my @tab;
for my $p ( @{$pt->table} ){
if ($p->cmndline =~ /\Q$pat\E/) {
push @tab, {pid => $p->pid, start => $p->start};
}
}
say $_->{pid} for (sort {$b->{start} <=> $a->{start}} @tab);
关于Perl pgrep 返回多个 pid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31757322/