perl - 为什么Perl的系统返回值不是我期望的?

标签 perl exit-code

首先让我解释一下我要完成的任务。本质上有两个 Perl 脚本。一个是我称之为带有 UI 的主脚本。运行此脚本的用户将看到他可以从菜单中调用的其他脚本的列表。此列表通过自定义配置文件加载。主要脚本的目的是能够在未来根据需要添加其他脚本,而无需更改源代码,并作为 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.

这就是奇怪的地方。我有一个检查文件系统使用情况的脚本。一旦选中,它将以适当的值退出,供主脚本处理。

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;

主脚本看到: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 尝试过这个,它也是一样的。出于某种原因,我的印象是我遗漏了一些非常明显的东西......

最佳答案

这是定义的行为。

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

The return value is the exit status of the program as returned by the wait call. To get the actual exit value, shift right by eight (see below).

Return value of -1 indicates a failure to start the program or an error of the wait(2) system call (inspect $! for the reason).

关于perl - 为什么Perl的系统返回值不是我期望的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3882677/

相关文章:

regex - 更改特定字母后的所有出现位置

perl - 如何在perl one liner中查看n或p开关生成的代码块

perl:打印对象属性

java - Knime批处理模式: Java returned exit code 4

c++ - 退出(0)不结束程序

batch-file - 从批处理脚本返回值

perl - 使用 Fcntl : Baffling bug involving 'use' and 'require' 锁定文件

linux - 使用 FIND 和 EXEC 在多个文件上执行需要文件名的 Perl 脚本

c# - 由于 Null 异常,.net core docker 容器在生产中退出并出现错误代码 139

java - 如何在 Windows 批处理文件中获取 Java 程序的退出状态