无法修改inter.pl时如何让system调用返回值在内部报错时非零
解决方案
你可以通过以下两种不需要修改inter.pl代码的方式实现需求:
- 方案1:重载Perl核心函数,拦截反引号执行结果和exit行为
利用Perl的动态重载特性,在加载inter.pl前注入钩子逻辑,捕获所有反引号执行的错误,覆盖最终退出码,只需修改ext.pl内的调用逻辑即可:
修改后的ext.pl代码:
逻辑说明:my $call_cmd = q{perl -e ' our $has_error = 0; BEGIN { # 重载反引号对应的readpipe核心函数 *CORE::GLOBAL::readpipe = sub { my $res = CORE::readpipe(@_); $has_error = 1 if $? != 0; return $res; }; # 重载exit函数,退出时优先返回错误标记 *CORE::GLOBAL::exit = sub { my $exit_code = shift // 0; CORE::exit($has_error ? 1 : $exit_code); }; } # 执行原inter.pl逻辑 do "inter.pl" or die $!; '}; my $rc = system($call_cmd); $rc = $rc >> 8; # 转换system返回值为实际进程退出码 print "$rc is rc\n";readpipe是Perl反引号调用对应的底层核心函数,提前重载后会拦截inter.pl内所有反引号操作,只要任意一次外部命令执行返回非零就标记错误;重载后的exit函数会在inter.pl调用exit时优先用错误状态作为最终退出码,完全不改动inter.pl的原有执行逻辑。
- 方案2:捕获子进程STDERR判断错误
不存在目标文件时cat命令会向STDERR输出错误信息,你可以在ext.pl中直接捕获inter.pl的STDERR内容,判断是否有错误输出即可自定义返回码:
实现代码:use IPC::Open3; use Symbol 'gensym'; my ($child_stdin, $child_stdout, $child_stderr); $child_stderr = gensym; # 兼容旧版本Perl stderr初始化逻辑 my $pid = open3($child_stdin, $child_stdout, $child_stderr, 'perl', 'inter.pl'); waitpid $pid, 0; my $rc = $? >> 8; # 读取STDERR内容判断是否存在错误 my $err_msg = do { local $/; <$child_stderr> }; $rc = 1 if $err_msg ne ''; print "$rc is rc\n";
内容的提问来源于stack exchange,提问作者AskQuestionsP
相关产品推荐
相关产品推荐

