首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >perl pgrep返回多个pids

perl pgrep返回多个pids
EN

Stack Overflow用户
提问于 2015-08-01 01:27:17
回答 2查看 2K关注 0票数 2

我有一些这样的perl代码来获得进程的pid (如果存在的话)。我想知道pgrep的返回状态,这样我就可以知道pid是否有效。以下是代码:

代码语言:javascript
复制
#!/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";

但是,每当我运行它时,我会得到以下信息:

代码语言:javascript
复制
0 Output1: 3054
Output2: 3056, 0

再跑一次

代码语言:javascript
复制
0 Output1: 3059
Output2: 3061, 0

但在系统中:

代码语言:javascript
复制
$ pgrep -n -f akonadiserver
1862

这里看到了几个问题:

1) pid返回一直在变化,很可能与grep进程本身相匹配。

2)找不到返回pid是否有效的方法。$?帮不上忙。

如何检查返回状态以及如何在perl中正确使用pgrep?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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

代码语言:javascript
复制
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);
票数 2
EN

Stack Overflow用户

发布于 2015-08-01 13:19:15

在我看来,pgrep返回由您正在寻找的进程启动的最新(-n)子进程的pid,至少在我的系统上是这样的。

我一直用ps做这种事,不如:

代码语言:javascript
复制
my $pid = (split(" ",`ps -A | grep \"akonadiserver\"`))[0];

相反,或

代码语言:javascript
复制
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;

使所有实例都运行到一个数组中,然后使用它执行您想要的操作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31757322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档