LINUX.ORG.RU

Прошу помощи с perl

 , ,


2

1

Доброго времени суток. Написал говноскриптскрипт на bash, в perl, увы не силён. Нужно переписать его на perl. Bash очень медленный из-за количества awk, к тому же в JSON выводит не верно.На perl есть модуль JSON, SNMP и вроде бы IPCALC. Вот само поделие:

#!/bin/bash

snmp=/usr/bin/snmpwalk
ipcalc=/usr/bin/ipcalc
community="sbrf"
ver="v2c"
ip=$1
community=$2
fl=/tmp/json

neigbor=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.14.10.1.1 | awk -F "IpAddress: " '{print $2}'`
ospfint=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.14.7.1.1 | awk -F "IpAddress: " '{print $2}'`

echo "{">$fl
echo "   \"data\" : [">>$fl
for arg in $neigbor
do

##################
for argg in $ospfint
do
mask=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.4.20.1.3.$argg | awk -F "IpAddress: " '{print $2}'`
net=`$ipcalc $argg $mask | grep Network: | awk '{print $2}'`
vhod=`$ipcalc $net /32 | grep Hostroute: | awk '{print $2}' | grep $arg`
if [ "$vhod" ]
then
gw=$argg
fi
done
###############



echo "      {">>$fl
echo "      \"{#IP}\" : \"$arg\",">>$fl
        echo "      \"{#GW}\" : \"$gw\",">>$fl
                index=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.4.20.1.2.$gw | awk -F "INTEGER: " '{print $2}'`
                echo "      \"{#INDEX}\" : \"$index\",">>$fl
                        alias=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.31.1.1.1.18.$index | awk -F "STRING: " '{print $2}'`
                        echo "      \"{#IFALIAS}\" : $alias,">>$fl
                        status=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.14.10.1.6.$arg.0 | awk -F "INTEGER: " '{print $2}'`
                        echo "      \"{#STATUS}\" : \"$status\"">>$fl
echo "      },">>$fl
done
echo "   ]">>$fl
echo "}">>$fl

cat $fl
rm $fl

Вот, что он выводит, в конце лишняя запятая:

{
   "data" : [
      {
      "{#IP}" : "10.200.70.69",
      "{#GW}" : "10.200.70.70",
      "{#INDEX}" : "14",
      "{#IFALIAS}" : "ROSTELEKOM (DSV), IP: 172.19.208.170, to OVC_9070 [2]",
      "{#STATUS}" : "8"
      },
      {
      "{#IP}" : "10.200.70.73",
      "{#GW}" : "10.200.70.74",
      "{#INDEX}" : "16",
      "{#IFALIAS}" : "ROSTELEKOM (DSV), IP: 172.19.208.170, to RVC_9070 [4]",
      "{#STATUS}" : "8"
      },
      {
      "{#IP}" : "10.200.70.77",
      "{#GW}" : "10.200.70.78",
      "{#INDEX}" : "13",
      "{#IFALIAS}" : "ROSTELEKOM, IP: 172.30.56.218, to OVC_9070 [1]",
      "{#STATUS}" : "8"
      },
      {
      "{#IP}" : "10.200.70.81",
      "{#GW}" : "10.200.70.82",
      "{#INDEX}" : "15",
      "{#IFALIAS}" : "ROSTELEKOM, IP: 172.30.56.218, to RVC_9070 [3]",
      "{#STATUS}" : "8"
      },
   ]
}

Кто возьмётся - буду очень благодарен. Спасибо.

★★

сколько платишь?

anonymous ()

На самом деле, интересует только это место:

for argg in $ospfint
do
mask=`$snmp -$ver -c $community $ip 1.3.6.1.2.1.4.20.1.3.$argg | awk -F "IpAddress: " '{print $2}'`
net=`$ipcalc $argg $mask | grep Network: | awk '{print $2}'`
vhod=`$ipcalc $net /32 | grep Hostroute: | awk '{print $2}' | grep $arg`
if [ "$vhod" ]
then
gw=$argg
fi
done

Не могу придумать, как сделать это на perl. Остальное всё более-менее понятно.

nixit ★★ ()
Ответ на: комментарий от nixit

Можно и так всё оставить, чуть более узнав про awk:

net=`$ipcalc $argg $mask | grep Network: | awk '{print $2}'`
==
net=`$ipcalc $argg $mask | awk '/Network:/{print $2}'`
ну и так, если бы блок входных данных, можно на регулярки как-то эффективнее переписать (это про лишнюю запятую).

conformist ★★★ ()
Ответ на: комментарий от zolden

работа с snmp средствами bash хороша только в самых простых случаях.

если делать тучу разных запросов к куче девайсов с парсингом результата - однозначно переписывать на любой знакомый язык где есть работа с snmp!

vel ★★★★★ ()

Могу порекомендовать, по возможности, заменить snmpwalk на snmpget.

И да, напиши что у тебя получилось/не получилось записать на Perl, так будет больше шансов получить какой-то ответ.

pru-mike ★★ ()
Ответ на: комментарий от pru-mike

Не получился кусок, который высчитывает локальный адрес, что я приводил выше, вот perl код:

#!/usr/bin/perl -w
use strict;
use SNMP;
use Data::Dumper;
use JSON;


my @json        = ();
my $idx         = 0;

die "Usage: $0 <host> <port> <community> [regex]" if scalar @ARGV < 3;
my $host = $0 =~ /.*\/(.*)/;

my $REGEX = $ARGV[3] ? $ARGV[3] : undef;
my $sess = new SNMP::Session(
    DestHost => "$ARGV[0]:$ARGV[1]",
    Community => "$ARGV[2]",
    UseNumeric => 1,
    NonIncreasing => 1,
    UseLongNames => 1,
    Version => "2c",
    Timeout => 8 * 1000000,
    Retries => 1 );
die $sess->{ErrorStr} if ($sess->{ErrorNum});

my ($ospfNbrIpAddr) = $sess->bulkwalk(0, 100, ['.1.3.6.1.2.1.14.10.1.1']);
die $sess->{ErrorStr} if ($sess->{ErrorNum});

foreach(@{$ospfNbrIpAddr}) {
#    print Dumper($_);

    my $ip = "${$_}[2]";

##################
my ($ospfint) = $sess->bulkwalk(0, 100, ['.1.3.6.1.2.1.14.7.1.1']);
die $sess->{ErrorStr} if ($sess->{ErrorNum});

foreach(@{$ospfint}) {
    #print Dumper($_);
    my $ospfip = "${$_}[2]";
    my $netmask = $sess->get([".1.3.6.1.2.1.4.20.1.3.$ospfip"]);
#print "$ospfip $netmask\n";
####### О Я Х.З, чё  тут делать дальше :( 
#### бла-бла-бла,
## gw = бла-бла
}
##################

    my ($index) = $sess->get([".1.3.6.1.2.1.4.20.1.2.$gw"]);
    my ($ifalias) = $sess->get([".1.3.6.1.2.1.31.1.1.1.18.$index"]);
    my ($status) = $sess->get([".1.3.6.1.2.1.14.10.1.6.$ip.0"]);
    my ($ifdescr) = $sess->get([".1.3.6.1.2.1.2.2.1.2.$index"]);
    my ($ifspeed) = $sess->get([".1.3.6.1.2.1.2.2.1.5.$index"]);
    
    $json[$idx] = { '{#IP}' => $ip, '{#GW}' => $gw, '{#SNMPINDEX}' => $index, '{#IFALIAS}' => $ifalias, '{#STATUS}' => $status, '{#IFDESCR}' => $ifdescr, '{#IFSPEED}' => $ifspeed/1000000};
    $idx++;
}

print "{\"data\":";
print to_json(\@json, {ascii => 1, pretty => 1});
print "}\n";

Пробую использовать разные модули для ip сетей, но что-то никак.

nixit ★★ ()
Последнее исправление: nixit (всего исправлений: 3 )
Ответ на: комментарий от conformist

В любом случае, на bash это будет слишком медленно, но - спасибо.

nixit ★★ ()
Ответ на: комментарий от nixit

net=`$ipcalc $argg $mask | grep Network: | awk '{print $2}'`
vhod=`$ipcalc $net /32 | grep Hostroute: | awk '{print $2}' | grep $arg`
if [ "$vhod" ]

Адок какой.

«Сеть», если что, вычисляется путем наложения маски на адрес узла кон’юнкцией:

ipmask2net ()
{
    local net_str_ref="$1" ip_str="$2" mask_str="$3"
    local a b c d hosts mask net abcd

    IFS='.' read a b c d <<< "$ip_str"

    (( ip = a * 256 ** 3 + b * 256 ** 2 + c * 256 + d,
       hosts = 2 ** (32 - mask_str),
       mask = 2 ** 32 - hosts,
       net = ip & mask ))

    for i in {3..0}; do
        (( abcd[i] = net / 256 ** i,
           net %= 256 ** i ))
    done

    declare -g $net_str_ref="${abcd[3]}.${abcd[2]}.${abcd[1]}.${abcd[0]}/${mask_str}"
}

$ ipmask2net net "10.200.70.92" "22"
$ echo "$net"
10.200.68.0/22

А что делает вторая строчка, я при всем старании осознать не могу. /32 — это подсеть из одного узла, не? Тут просто нечего вычислять.

Zmicier ★★★★★ ()
Ответ на: комментарий от Zmicier

Нужно по $ospfint определить маску - $mask, затем зная ip и маску вычисляем подсеть - $net. Затем, в цикле проверяем входит ли $neigbor в подсеть $net, если входит - $gw = $ospfint.

nixit ★★ ()
Ответ на: комментарий от nixit

Нужно по...

Вы это все сейчас к чему? Полагаете, что я буду вам всю программу писать?

vhod=`$ipcalc $net /32 | grep Hostroute: | awk '{print $2}' | grep $arg`

А что делает вторая строчка, я при всем старании осознать не могу. /32 — это подсеть из одного узла, не? Тут просто нечего вычислять.

проверяем входит ли $neigbor в подсеть $net

Подождите... Божечки ты мой! Это вы проверяете адрес на вхождение в сеть путем генерации полного списка всех адресов сети и грепа по нему?

«Баш» у него-де «очень медленный», ага.

Вхождение адреса A в сеть с префиксом N и маской M равно выражению N == A & M.

Zmicier ★★★★★ ()

Написал. Спасибо всем, кто пытался помочь. Использовал модули:Net::CIDR и NetAddr::IP.

nixit ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.