2012-11-22 40 views
3

我開發了一個小型的Nagios監控腳本,它基本上在給定的接口和端口上運行tcpdump,並在前10個捕獲的數據包中尋找特定的字符串。我正在監視一個系統,該系統可能會掛起並淹沒我的服務器並顯示特定的消息爲什麼我的Perl腳本在通過SSH執行時掛起?

我不是一個專業的Perl程序員,但我相信我已經對待過所有的期待。

在本地運行此腳本結束就好了,並將控制檯返回給我。但是,當我嘗試通過ssh(ssh user @ host -i private_key'/path/script.pl')通過我的Nagios服務器運行它時,腳本成功執行,我得到退出消息,但是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; 
} 

任何幫助深表感謝。

謝謝!

+1

任何想法,爲什麼你需要叉在這裏?如果要報警,試試命令'timeout 5/usr/sbin/tcpdump ....' –

+0

tshark有自己的超時時間'tshark -a'持續時間:1'' –

+1

btw,如果你需要檢查文件存在,使用'if !-f「/tmp/capture.txt」){..' –

回答

2

看這裏:出現

#!/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 

的問題,因爲你的系統一個新的進程和過程不從父進程得到信號。

的解決方案是隻使用exec(),而不是``system()作爲exec()不派生新進程:

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

非常感謝您的幫助!執行命令取得了訣竅,但仍然認爲這是一種解決我的問題的更優雅的方式,我甚至不需要求助於腳本。 –

相關問題