如何确定Java进程是否在Perl中运行

时间:2012-09-26 00:17:52

标签: perl process grep ps

我有一套小型Java应用程序,它们都编译/打包到<name-of-the-app>.jar并在我的服务器上运行。偶尔其中一个会抛出异常,窒息而死。我正在尝试编写一个快速脏的Perl脚本,它将定期轮询以查看是否所有这些可执行JAR仍在运行,如果它们中的任何一个都没有运行,请给我发一封电子邮件并通知我哪一个已经死了。< / p>

要手动确定,我必须为我要检查的每个应用运行ps -aef | grep <name-of-app>。例如,要查看myapp.jar是否作为进程运行,我运行ps -aef | grep myapp,并查找描述代表myapp.jar的JVM进程的grep结果。这种手动检查现在变得乏味,是自动化的主要候选者!

我正在尝试实现检查进程是否正在运行的代码。我想将其设为sub,接受可执行JAR的名称并返回truefalse

sub isAppStillRunning($appName) {
    # Somehow run "ps -aef | grep $appName"

    # Somehow count the number of processes returned by the grep

    # Since grep always returns itself, determine if (count - 1) == 1.
    # If so, return true, otherwise, false.
}

我需要能够传递sub应用程序的名称,运行我的正常命令,并计算grep返回的结果数。由于运行grep总是会导致至少一个结果(grep命令本身),我需要逻辑说明(#of results - 1)是否等于1,然后我们知道应用程序正在运行。

我是Perl的新手,我很难搞清楚如何实现这个逻辑。到目前为止,这是我最好的尝试:

sub isAppStillRunning($appName) {
    # Somehow run "ps -aef | grep $appName"
    @grepResults = `ps -aef | grep $appName`;

    # Somehow count the number of processes returned by the grep
    $grepResultCount = length(@grepResults);

    # Since grep always returns itself, determine if (count - 1) == 1.
    # If so, return true, otherwise, false.
    if(($grepResultCount - 1) == 1)
        true
    else
        false
}

然后从同一个Perl脚本中调用该方法,我我会运行:

&isAppStillRunning("myapp");

任何有关定义sub然后使用正确的应用程序名称调用它的帮助都非常感谢。提前谢谢!

3 个答案:

答案 0 :(得分:4)

使用CPAN的Proc::ProcessTable模块会容易十亿倍。以下是它的外观示例:

use strict;
use warnings;
use Proc::ProcessTable;

...
sub isAppStillRunning { 
    my $appname = shift;
    my $pt = Proc::ProcessTable->new;
    my @procs = grep { $_->fname =~ /$appname/ } @{ $pt->table };

    if ( @procs ) { 
        # we've got at least one proc matching $appname. Hooray!
    } else { 
        # everybody panic!
    }
}

isAppStillRUnning( "myapp" );

要记住的一些注意事项:

  • 开启strictwarnings。他们是你的朋友。
  • 您没有使用prototypes指定子例程参数。 (Perl中的原型完全不同,你不需要它。)使用shift@_数组中获取参数。
  • 不要使用&来调用子程序;只需使用它的名字。
  • 在标量上下文中计算的数组(包括其内部if)是否为您提供了大小。 length不适用于数组。

答案 1 :(得分:3)

你的潜艇几乎在那里,但最后的if-else结构必须得到纠正,在某些情况下,Perl成语可以让你的生活更轻松。

Perl有原型,但他们吮吸

sub isAppStillRunning($appName) {

不起作用。而是使用

sub isAppStillRunning {
  my ($appName) = @_;

@_数组包含函数的参数。 Perl有一些简单的原型(sub name(&$@) {...}语法),但它们已被破坏,并且是一个高级主题,所以不要使用它们。

Perl内置Grep

`ps -aef | grep $appName`;

返回一(1)个字符串,可能包含多行。您可以将输出拆分为换行符,并手动grep,这比插入变量更安全:

my @lines   = split /\n/ `ps -aef`;
my @grepped = grep /$appName/, @lines;

您还可以使用open函数明确打开ps的管道:

my @grepped = ();
open my $ps, '-|', 'ps -aef' or die "can't invocate ps";
while (<$ps>) {
  push @grepped if /$appName/;
}

这完全相同,但风格更好。它会读取ps输出中的所有行,然后将$appName的所有行推送到@grepped数组中。

标量与列表上下文

Perl有这种不寻常的东西叫做“上下文”。有列表上下文标量上下文。例如,子例程调用采用参数列表 - 因此这些列表(通常)具有列表上下文。相比之下,连接两个字符串是一个标量上下文。

根据其上下文,数组的行为会有所不同。在列表上下文中,它们会评估其元素,但在标量上下文中,它们会评估其元素的数量。因此无需手动计算元素(或使用适用于字符串的length函数)。

所以我们有:

 my @array = (1, 2, 3);
 print "Length: ", scalar(@array), "\n"; # prints "Length: 3\n"
 print "Elems: ", @array, "\n";          # prints "Elems: 123\n";
 print "LastIdx: ", $#array, "\n";       # prints "LastIdx: 2\n";

最后一个表单$#array是数组中的最后一个索引。除非您插入特殊变量,否则与@array - 1相同。

scalar函数强制标量上下文。

Perl没有布尔

Perl没有布尔数据类型,因此没有truefalse个关键字。相反,除非另有说明,否则所有值均为真。错误的值是:

空字符串"",数字零0,字符串零"0",特殊值undef以及其他一些您不会遇到的奇怪之处。

因此,通常将1设为true,将0设为false。

if / else构造需要花括号

所以你可能意味着:

if (TEST) {
  return 1;
} else {
  return 0;
}

return TEST相同,其中TEST是条件。

终极减少

使用这些技巧,你的潜艇可以写成

sub isAppStillRunning {
   return scalar grep /$_[0]/, (split /\n/, `ps -aef`);
}

这将返回包含您的应用名称的行数。

答案 2 :(得分:1)

您可以像这样修改您的例程:

sub isAppRunning {
    my $appName = shift;
    @grepResults = `ps -aef | grep $appName`;
    my $items = 0;
    for $item(@grepResults){
        $items++;
    }
    return $items;
}

这将迭代@grepResults并允许您在必要时检查$ item。

这样调用它应该返回进程数:

print(isAppRunning('myapp') . "\n");