我有一些这样的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?
发布于 2015-08-02 19:35:11
从Perl脚本运行`pgrep -n -f akonadiserver`等同于从终端运行sh -c "pgrep -n -f akonadiserver"。
来自perlop:
qx/STRING/: 一个字符串,它(可能)被内插,然后作为/bin/sh或其等效的系统命令执行。
问题是,使用-f选项和pgrep将匹配用于调用进程的完整命令行。这还将包括当前的pgrep命令,因为它的命令行看起来像sh -c "pgrep -n -f akonadiserver",它将匹配字符串"akonadiserver"。由于您还在pgrep中使用了pgrep标志,所以它只返回与"akonadiserver"匹配的最新进程,这很可能是pgrep命令本身(sh -c "pgrep -n -f akonadiserver")。这就解释了为什么你得到了错误的进程标识。
然而,它并没有解释为什么它仍然从终端窗口工作。原因是,在终端窗口中,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);发布于 2015-08-01 13:19:15
在我看来,pgrep返回由您正在寻找的进程启动的最新(-n)子进程的pid,至少在我的系统上是这样的。
我一直用ps做这种事,不如:
my $pid = (split(" ",`ps -A | grep \"akonadiserver\"`))[0];相反,或
my @pids = map{ $_ =~ /(\d+)/; $1 }split("\n", `ps -A | grep \"akonadiserver\"` );
print "mutiple instances: @pids\n" if @pids > 1;
print "pid: ".$pids[0]."\n" if @pids == 1;使所有实例都运行到一个数组中,然后使用它执行您想要的操作。
https://stackoverflow.com/questions/31757322
复制相似问题