最近做一个升级相关的任务,需要在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;
}
http://computer-programming-forum.com/53-perl/9c245f9c0626d2ed.htm