gpt4 book ai didi

perl - 为什么我的 Perl 脚本在通过 SSH 执行时挂起?

转载 作者:行者123 更新时间:2023-12-02 02:09:22 24 4
gpt4 key购买 nike

我开发了一个小型 Nagios 监控脚本,它基本上在给定的接口(interface)和端口上运行 tcpdump,并在前 10 个捕获的数据包中查找特定的字符串。我正在监视一个系统,该系统可能会挂起并用特定消息淹没我的服务器。

我不是专业的 Perl 程序员,但我相信我已经处理了所有可能的期望。

在本地运行这个脚本很好,并将控制台返回给我。但是,当我尝试通过我的 Nagios 服务器运行它时,通过 ssh (ssh user@host -i private_key '/path/script.pl'),脚本成功执行,我收到退出消息,但是,ssh 没有导出。我必须按 Ctrl+C 或按几次回车才能让 bash 返回给我。出于显而易见的原因,使用 check_by_ssh 运行它会给我一个插件超时错误。

我很确定它与我正在使用的 fork() 有关,但我不知道它有什么问题。

#!/usr/bin/perl -w
use strict;
use warnings;
use Getopt::Long;

my $RC_OK = 0;
my $RC_WARNING = 1;
my $RC_CRITICAL = 2;
my $RC_UNKNOWN = 3;

my $GREP_RC = undef;

my $PORT = undef;
my $INT = undef;
my $STRING = undef;

my $PID = undef;

# Handler principal de alarme de timeout
$SIG{ALRM} = sub {
print "UNKNOWN: Main script timed out!\n";
exit $RC_UNKNOWN;
};

# Inicio contagem global
alarm(8);

# Coleta parametros
GetOptions ("port=s" => \$PORT,
"interface=s" => \$INT,
"string=s" => \$STRING);

# Sanity check de parametros
if((not defined $PORT) || (not defined $STRING)) {
print "Usage: ./check_stratus.pl -p=PORT -i=INTERFACE -s=STRING\n";
exit $RC_UNKNOWN;
}

# Capturando pelo tcpdump
defined($PID = fork()) or die "Problema ao criar o fork: $!\n";
if ($PID == 0) {

# Handler secundario de alarme de timeout
$SIG{ALRM} = sub {
exit 1;
};

# Captura no maximo por 5 segundos, ou 10 pacotes
alarm(5);

`sudo /usr/sbin/tcpdump -nX -s 2048 -c 10 -i $INT port $PORT > /tmp/capture.txt 2>&1`;

# Checando se o tcpdump rodou com sucesso
if ($? != 0) {
print "Erro ao executar \"/usr/sbin/tcpdump -nX -s 2048 -c 1 -i $INT port $PORT > /tmp/capture.txt\", verifique o arquivo de saida para mais detalhes.\n";
exit $RC_UNKNOWN;
}
exit $RC_OK;
}

# Espera o filho encerar...
waitpid($PID, 0);

# Verificando se o arquivo capturado esta ok
`/bin/ls /tmp/capture.txt`;

if ($? != 0) {
print "Erro ao encontrar o arquivo /tmp/capture.txt\n";
exit $RC_UNKNOWN;
}

# Executando grep da string em cima da captura
`/bin/grep $STRING /tmp/capture.txt`;

# Verificando resultado do grep
if ($? == 0) {
print "Foi encontrada a string \"$STRING\" na captura do tcpdump escutando na interface $INT e na porta $PORT!\n";
exit $RC_CRITICAL;
}

if ($? == 256) {
print "Nao foi encontrada a string \"$STRING\" na captura do tcpdump escutando na interface $INT e na porta $PORT.\n";
exit $RC_OK;
} else {
print "Erro desconhecido! Codigo do grep foi $?\n";
exit $RC_UNKNOWN;
}

非常感谢任何帮助。

谢谢!

最佳答案

看这里:

#!/usr/bin/perl
use strict;
my $PID;
defined($PID = fork()) or die "no fork works";
if ($PID == 0) {

# Handler secundario de alarme de timeout
$SIG{ALRM} = sub {
exit 1;
};

# Captura no maximo por 5 segundos, ou 10 pacotes
alarm(1);
`sleep 100`;
}
waitpid($PID, 0);

/tmp$ ps xawww |grep sleep
1705 pts/2 S+ 0:00 grep sleep
host:/tmp$ time /tmp/test.pl

real 0m1.008s
user 0m0.000s
sys 0m0.004s
host:/tmp$ ps xawww |grep sleep
1708 pts/2 S 0:00 sleep 100
1710 pts/2 S+ 0:00 grep sleep

出现这个问题是因为你的系统 fork 了一个新的进程,而那个进程没有从父进程得到信号。

解决方案是使用 exec() 而不是 ``system() 作为 exec()不 fork 新进程:

    alarm(1);
exec("sleep 100");

关于perl - 为什么我的 Perl 脚本在通过 SSH 执行时挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13519380/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com