关于Perl使用system执行外部命令的返回值

高玮
2023-12-01

问题及处理

最近做一个升级相关的任务,需要在Perl脚本中调用Python脚本,由于Perl脚本中的老代码都是使用的system()函数来调用Python脚本,我就直接仿写了,在Python中用sys.exit(n)退出。当Python返回5时,结果Perl拿到的却是1280,Perl函数调用如下:

sub deploy_cert { 
    my $appMode = getAppMode();
    if (($appMode eq "MEDIA") || ($appMode eq "MEDIA")) { 
        my $sec_result = system("python $comm_script --DeployCert"); 
        return $sec_result; 
    } 
    return 0; 
}

一时有些懵逼,先单独在bash执行Python发现返回值没问题,排除了Python脚本的问题,1280这么大的值也不会是ASCII码转换这类问题,所以问题一定在system(cmd)函数。

实际上,Perl的system(cmd)执行外部命令时也是fork了子进程并用wait等待了子进程的退出,实际处理更为复杂,请参考perldoc -f system,真相就是:system(cmd)返回值是16位的数字,高8位保存了cmd退出时的返回值,低8位默认是0,如果子进程是收到信号意外退出(core dump),那么第8个位CD就会被置成1,最低的7个位保存使子进程退出的信号值。

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | Exit code |CD |Signal number |

所以,前面1280就是0000010100000000。对于使用system(cmd),默认地,返回值0就是执行cmd成功,所有非0值都是执行不成功,和shell命令一样。一般的命令调用判断返回非0就报错退出了,如果要自己处理更多的返回值就要多写几行代码了:

sub deploy_cert { 
    my $appMode = getAppMode(); 
    if (($appMode eq "MEDIA") || ($appMode eq "MEDIA")) { 
        my $sec_result = system("python $comm_script --DeployCert"); 
        my $exit_code = ($sec_result & 0xff00) >> 8; 
        my $core_dump = ($sec_result & 0x0080); 
        my $signal_no = ($sec_result & 0x007f); 
        if ($signal_no) { 
            print "Process killed by signal $signal_no"; 
            print $core_dump ? " (core dumped)\n" : "\n"; 
        } else { 
            print "Process exited with status $exit_code\n"; 
        } 
        return $exit_code; 
    }
     return 0; 
}

References

http://computer-programming-forum.com/53-perl/9c245f9c0626d2ed.htm

 类似资料: