IPC::Open3 запускает snmpwalk с поведением, отличным от поведения отдельной команды snmwalk

Я сделал собственную подпрограмму для запуска различных команд терминала в Perl с использованием Open3.

Я столкнулся со странной проблемой с snmpwalk, когда я запускаю команду в терминале, она работает, а с Open3 - нет.

Саб это:

sub run_cmd {
    my ( $cmd, @args ) = @_;
    my ( $infh, $outfh, $errfh, $pid, $out, $err );

    use Symbol 'gensym';
    $errfh = gensym();    # open3 does not init stderr, we have to do it.

    output( "run_cmd: $cmd @args\n", 2, 1 ); #for debug
    eval { $pid = open3( $infh, $outfh, $errfh, $cmd, @args ); } or do {
        if ($@) {
            output("Error: open3 error $@\n");
            exit $CODES{CRITICAL}; #exit 2;
        }
    };
    {   # anonym block to limit $/ redefinition
        local $/ = undef;
        $out = <$outfh>;
        $err = <$errfh>;
    }
    return ( $out, $err );
}

Я называю это с помощью:

 ($res, $err) = run_cmd("snmpwalk", "-c public -v1", "somehostname", "NETAPP-MIB::aggrName");

Если я хочу запустить следующую команду:

snmpwalk -c public -v1 somehostname NETAPP-MIB::aggrName

Он возвращается как $err:

snmpwalk: имя безопасности не указано

Если я запускаю ту же самую команду в терминале, она возвращает мои результаты:

NETAPP-MIB::aggrName.1 = STRING: SAS2

NETAPP-MIB::aggrName.2 = СТРОКА: SATA1

...

Я обнаружил, что NET::SNMP может решить мою проблему, но я не могу установить его из-за защищённой ОС Linux без возможности установки.

Я действительно не понимаю, почему это не работает.

перл -v: 5.8.8

Спасибо!


person user3613475    schedule 07.05.2014    source источник
comment
Если у вас достаточно прав для установки скрипта, у вас достаточно прав для установки модуля.   -  person ikegami    schedule 07.05.2014
comment
$out = <$outfh>; $err = <$errfh>; вызовет взаимоблокировку, если дочерний элемент достаточно выведет в STDERR. Я рекомендую использовать IPC::Run3 или IPC::Run вместо все еще очень низкоуровневого IPC::Open3. Если вы хотите придерживаться IPC::Open3, вам придется использовать IO::Select, потоки или какую-либо форму асинхронного ввода-вывода, чтобы избежать возможности взаимоблокировки.   -  person ikegami    schedule 08.05.2014


Ответы (1)


Проблема заключается в аргументе "-c public v1":

($res, $err) = run_cmd("snmpwalk", "-c public -v1", "somehostname", "NETAPP-MIB::aggrName");

Функция IPC::Open3 open3() выполняет ветвление, а затем exec. exec обходит оболочку, когда дается список аргументов. Поэтому список нужно разбить на отдельные аргументы:

($res, $err) = run_cmd("snmpwalk", "-c", "public", "-v1", "somehostname", "NETAPP-MIB::aggrName")
person dwarring    schedule 07.05.2014
comment
Точно. Чтобы уточнить, выводится сообщение «Нет указанного имени безопасности», потому что snmpwalk считает, что вам нужен SNMP v3, который является версией по умолчанию, если не указан флаг -v. Итак, очевидно, что флаг -v1 не был получен, как указал snoopy. - person Jolta; 08.05.2014