Почему возвращаемое значение системы Perl не то, что я ожидаю? - PullRequest
2 голосов
/ 07 октября 2010

Позвольте мне начать с объяснения того, чего я пытаюсь достичь.По сути, есть два сценария Perl.Одним из них является то, что я называю основным сценарием с пользовательским интерфейсом.Пользователь, который запускает этот скрипт, увидит список других скриптов, которые он может вызвать из меню.Этот список загружается через пользовательский файл конфигурации.Цель основного сценария - иметь возможность добавлять другие сценарии в будущем по мере необходимости без изменения источника и запускаться либо как задание cron (неинтерактивный режим), так и по мере необходимости пользователя (интерактивный режим).В соответствии с политикой компании я не имею права публиковать весь сценарий, поэтому я опубликую раздел выбора пользователя в интерактивном режиме:

for($i = 0;$i < @{$conf}+1;$i++)
    {
        if($i % 2 == 1 || $i == 0)
        {
            next;
        }
        print $n++ . ". @{$conf}[$i-1]\n";
    }
    print "(health_check) ";

    #
    # User selection
    #

    my $in = <>;
    chomp($in);

    if($in =~ /[A-Za-z]/)
    {
        write_log("[*] Invalid Selection: $in");
        print "\n<<<<<<<<<<<<>>>>>>>>>>>>>\n";
        print ">>> Invalid Selection <<<\n";
        print "<<<<<<<<<<<<>>>>>>>>>>>>>\n";
    }
    elsif($in == 0)
    {
        write_log("Exiting interactive mode");
        last;
    }
    elsif(scalar($scripts[$in]))
    {
        write_log("[*] running: $scripts[$in]");
        $rez = system('./' . "$scripts[$in]");

        if($rez == 0b00)
        {
            printf("%s: [OK]\n",$scripts[$in]);
        }
        elsif($rez == 0b01)
        {
            printf("%s: [WARNING]\n",$scripts[$in]);
        }
        elsif($rez == 0b11)
        {
            printf("%s: [NOT OK]\n",$scripts[$in]);
        }
        else
        {
            print "UNKOWN ERROR CODE: $rez\n";
        }
    }
    else
    {
        write_log("[*] Invalid Selection: $in");
        print "\n<<<<<<<<<<<<>>>>>>>>>>>>>\n";
        print ">>> Invalid Selection <<<\n";
        print "<<<<<<<<<<<<>>>>>>>>>>>>>\n";    
    }

    print "\n\nPress return/enter to continue...";
    <>;
}

write_log("Exiting interactive mode");

}

@ {$ conf} является ссылкойк списку доступных скриптов.У этого есть и имя сценариев и путь к сценарию.

$i is used for looping.
$n is the script number which is used for the user to select which script to run.
$in is the user input in decimal value to select which script to run.
$scripts is the actual name of the script and not the path to the script.
$rez is the return code from the scripts.

Вот где это становится странным.У меня есть скрипт, который проверяет использование файловой системы.После того, как это будет проверено, он выйдет с соответствующим значением для обработки сценарием Main.

0 is Ok
1 is Warning
2 is Alert
3 is Warning + Alert

Вот соответствующая часть скрипта проверки файловой системы:

    if(check_hdd($warning_lvl, $alert_lvl))
{
    $return_val = $return_val | 0b01;
}

if(check_hdd($alert_lvl))
{
    $return_val = $return_val | 0b10;
}

exit $return_val;

Подпрограмма check_hdd вернет 1, если что-то находится между двумя аргументами, которые вставлены(например, он вернет 1, если обнаружит, что что-то среднее между диапазоном - это использование файловой системы в процентах со значением по умолчанию 100% для второго аргумента).

Так вот, это становится странным ...

Если, например, скрипт hdd возвращает 1. Главный скрипт увидит 256.

Итак, я вошел в скрипт hdd и заставил его вернуть 256.

exit 256;

Mainсценарий увидел: 0. Итак, я сделал это с различными значениями и создал небольшую таблицу.

HDD_Check Exit Value            Main is seeing Exit Value as
         1                                    256
         256                                    0
         257                                  256
         258                                  512
         259                                  768

Ааа.Интригующий.Позволяет преобразовать это в двоичный.

HDD_Check Exit Value (Base 2)       Main is seeing Exit Value as (Base 2)
         0b0000000001                             0b0100000000
         0b0100000000                             0b0000000000
         0b0100000001                             0b0100000000
         0b0100000010                             0b1000000000
         0b0100000011                             0b1100000000

Странно.Похоже, что при передаче значения выполняется следующее:

return_value = return_value << 8

Итак, теперь, когда длинное объяснение закончено, у кого-нибудь есть идеи?Я также попробовал это с die вместо exit, и он делает то же самое.И почему-то у меня сложилось впечатление, что это что-то очень очевидное, чего мне не хватает ...

1 Ответ

10 голосов
/ 07 октября 2010

Это определенное поведение.

http://perldoc.perl.org/functions/system.html

Возвращаемым значением является состояние выхода программа, возвращаемая ожиданием вызов. Чтобы получить фактическое значение выхода, сдвиг вправо на восемь (см. ниже).

Возвращаемое значение -1 указывает на ошибку при запуске программы или ошибку системного вызова wait (2) (проверьте $!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...