Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我的Perl脚本在通过SSH执行时挂起?_Perl_Ssh_Fork_Nagios - Fatal编程技术网

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

为什么我的Perl脚本在通过SSH执行时挂起?,perl,ssh,fork,nagios,Perl,Ssh,Fork,Nagios,我开发了一个小型Nagios监控脚本,它基本上在给定的接口和端口上运行tcpdump,并在前10个捕获的数据包中查找特定的字符串。我正在监视一个系统,该系统可能会挂起并用特定消息淹没我的服务器 我不是一个专业的Perl程序员,但我相信我已经处理了所有可能的期望 在本地运行此脚本的结果很好,并将控制台返回给我。但是,当我试图通过Nagios服务器通过ssh(ssh)运行它时user@host-i private_key'/path/script.pl'),脚本成功执行,我得到退出消息,但是ssh没

我开发了一个小型Nagios监控脚本,它基本上在给定的接口和端口上运行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);

出现此问题的原因是系统分叉一个新进程,而该进程没有从父进程获取信号

解决方案是使用
exec()
而不是
`
system()
,因为
exec()
不会产生新的进程:

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

知道你为什么需要叉子吗?如果要报警,请尝试命令
timeout 5/usr/sbin/tcpdump….
tshark拥有自己的超时
tshark-a'duration:1'
btw,如果需要检查文件是否存在,请使用
if(!-f)/tmp/capture.txt){..
非常感谢您的帮助!exec命令成功了,但是,超时是解决我的问题的一种更优雅的方法,我甚至不必求助于分叉脚本。
    alarm(1);
    exec("sleep 100");