如何在shell或perl脚本中监视特定的进程名列表

时间:2016-08-31 16:44:58

标签: bash perl shell scripting sh

我试图找出监视shell脚本中进程ID列表的最佳方法。我不想全部监控它们,只是一个自定义列表。

例如: 如果我有进程名称::

Orange-TE--02
Orange-TE--03
Apple-JI--01
Orange-TE--09
Orange-JI--06

我正在尝试编写一个只监视Orange-TE-02,Apple-JI-01,Orange-JI-06的脚本,因此如果其中任何一个出现故障,将发送一个电子邮件警报哪个过程失败了。如果Orange-TE-03,Orange-TE-09熄火,没有任何反应。

这是流程的输出' process.sh -s

name            Process                         Pid
---------------- ------------------------------- ----
tneal01        Orange-JI--06                     3443
tneal01        Orange-TE--09                     2233
tneal01        Orange-JI--01                     5533
tneal01        Apple-TE--03                     9384
tneal01        Orange-TE--02                     4992

我正在考虑将结果输出到文件并列出预期的进程名称列表,那些不匹配的列表发送电子邮件说

Alert Process:
Apple-TE--03 
Orange-TE--02 
Are down

不确定如何做到这一点。任何帮助将不胜感激。

谢谢!

2 个答案:

答案 0 :(得分:2)

更新添加了电子邮件和评论的代码 更新添加了后续问题的答案

使用Perl脚本

use warnings 'all';
use strict;

my @watch = qw(Orange-TE--02 Apple-JI--01 Orange-JI--06);

# Extract second column from the table of running processes, drop header line
my @running = map { (split)[1] } `process.sh -s`; 
shift @running;

my @down;
foreach my $proc_name (@watch) {
    push @down, $proc_name  if not grep { /^$proc_name$/ } @running;
}
print "$_ is down\n" for @down;
send_email(@down) if @down;

sub send_email {
    my @data = @_;
    # Write a file  (but use File::Temp) and attach for a multi-line message
    my $down_file = "services_down.$$";
    open my $fh, '>', $down_file  or die "Can't open $down_file: $!";
    print $fh "$_\n" for @data; 
    close $fh;
    my $cmd = "echo \"Services down: @data. See attached.\" | " .
        "mailx -a $down_file -s \"Services down\" user\@email";
    # Or, for an email with a single-line body
    # my $cmd = "echo @data | mailx -s \"Services down\"  user\@email";
    system($cmd) == 0  or do {
        warn "Error with system($cmd): $!";
        warn "File $down_file left behind for debugging. Remove.";
        return;
    };
    unlink $down_file  or warn "Can't unlink $down_file $!";
    return 1;
}   

电子邮件说明。如果使用mailx,我们无法将换行符输入其中。因此,如果电子邮件需要具有每行服务,我们可以写入文件并将文件附加到邮件中。该文件已删除,如果您希望保留它,请更改该文件。我用PID($$)标记其名称,但注意这还不够 - 如果在进程中写入多个此类文件,则只保留最后一个。最好将核心File::Temp用于临时文件。或者使用注释掉的版本,整个身体都在一行中。然后没有理由写这个文件。只有在运行system时出现问题,才会触发$cmd上的错误检查。如果它运行正常但电子邮件本身失败(例如,地址错误),则无法检测到。所有这一切的替代方案是使用许多模块之一来发送电子邮件。

请注意,List::UtilList::MoreUtils有许多有用的例程,因此上述内容可以为if none { /.../ } @running;。这里的改进是微妙的,但往往是非常直接的。

我不知道应该如何监控它,但你可以把它放在一个循环中,如

for (1..$max_time_steps) {
    # code above
    sleep 1;
}

或者你可以在while (1) { ... }内部以适当的条件确定何时爆发。

这个问题的一个变种被问到了一个新的问题,这个问题被搁置(正如我完成输入代码并解释为什么我决定在那里回答)并且现在已经过去了。看到它的不同之处。以下是 问题的答案。差异显示在最后。

使用哈希来运行process.sh -s返回的进程,其中每个进程名是一个键,其中包含最后一列的值(PID /“向下”)。 process.sh的输出首先被送入数组,以便丢弃标题。

use warnings 'all';
use strict;

my @watch = qw(Orange-TE--02 Apple-TE--03 Orange-JI--01);

my @procs_info = `process.sh -s`;
my %running = map { (split)[1,2] } @procs_info[2..$#procs_info]; 

print "$_ => $running{$_}\n" for keys %running;  # just to see it

my @down;
foreach my $proc_name (@watch) 
{
    push @down, $proc_name  
        if !exists $running{$proc_name} 
        or $running{$proc_name} eq 'Down';
}

if (@down) { 
    print "$_ is down\n" for @down;
    # send email
}

我将@down添加到受监视的进程中,如果它甚至不在运行的进程列表中。如果错了就改变。

对于记录,这里是另一个问题(以及我如何测试)的不同之处

my @procs_info = <DATA>;    # The only change to the above code

# same code ...

__DATA__
name            Process                         Pid
---------------- ------------------------------- ----
tneal01        Orange-JI--06                     3443
tneal01        Orange-TE--09                     Down
tneal01        Orange-JI--01                     5533
tneal01        Apple-TE--03                      Down
tneal01        Orange-TE--02                     4992

答案 1 :(得分:0)

processes_to_be_tracked=('Apple-TE--03' 'Orange-TE--02')
running_processes=( $(process.sh -s | awk '{print $2}') )
non_running=()
for process_name in ${processes_to_be_tracked[@]}; do
    if [[ "${running_processes[*]}" == *$process_name* ]]; then
        echo "$process_name is running"
    else
        echo "$process_name is not running"
        non_running+=($process_name)
    fi
done
send-alert-mail-with-names-of-dead-processes "${non_running[*]}"