Linux CTRL+;C和Perl';s system()函数-脚本未被中断
我有一个Perl脚本,它使用Linux CTRL+;C和Perl';s system()函数-脚本未被中断,linux,perl,Linux,Perl,我有一个Perl脚本,它使用system()函数按顺序启动一些程序。当脚本正在运行且程序正在运行时,我键入CTRL+C。我希望程序终止(发生),但我也希望脚本终止(未发生) 我已经建立了一个最低限度的工作示例。下面是Perl脚本: #!/bin/env perl sub run_the_test { local($name, $_) = @_; print "Starting $name\n"; return system("program.bash $name"); }
system()
函数按顺序启动一些程序。当脚本正在运行且程序正在运行时,我键入CTRL+C。我希望程序终止(发生),但我也希望脚本终止(未发生)
我已经建立了一个最低限度的工作示例。下面是Perl脚本:
#!/bin/env perl
sub run_the_test {
local($name, $_) = @_;
print "Starting $name\n";
return system("program.bash $name");
}
&run_the_test("test1");
&run_the_test("test2");
&run_the_test("test3");
这是外部“程序”:
我启动脚本并发出CTRL+Z。然后我执行了一个ps-opid、pgrp、cmd
来列出流程信息。我可以看到脚本、它调用的bashshell和sleep命令都属于同一个进程组。当sleep
正在执行时,我还希望它是前台进程组。我读了一些关于Linux、信号和终端的内容,发现CTRL+C应该向整个前台进程组发送一个中断,从而终止脚本
我还尝试使用exec()
而不是system()
。这样,脚本在触发CTRL+C时会停止,但不会运行到test1之后
有人能解释一下这里发生了什么吗?很好,您已经调查并了解了流程组。解释这些通常是这样一个问题的难点。因此,您知道中断信号
SIGINT
应该发送到进程组中的所有进程,包括您的perl
进程
但是SIGINT
并不总是致命的。它可以被捕获或忽略。子进程运行时,system()
函数忽略SIGINT
。此功能使您可以中断已坏掉的子进程,而不会杀死父进程
在perlfunc中,system()
的描述是:
因为在执行过程中忽略了“SIGINT”和“SIGQUIT”
“系统”,如果您希望您的程序在收到
您需要根据这些信号自行安排
返回值
@args = ("command", "arg1", "arg2");
system(@args) == 0
or die "system @args failed: $?"
这就是你需要做的。检查system()
的返回值,并在子进程失败时采取您认为合适的任何操作。如果要将SIGINT
与其他类型的故障区分开来,perlfunc中的下一段将有所帮助:
如果您想手动检查“系统”的故障,您可以检查
通过检查所有可能的故障模式$?像这样:
if ($? == -1) {
print "failed to execute: $!\n";
}
elsif ($? & 127) {
printf "child died with signal %d, %s coredump\n",
($? & 127), ($? & 128) ? 'with' : 'without';
}
else {
printf "child exited with value %d\n", $? >> 8;
}
例如,您可以在运行测试中执行此操作:
my $r = system("program.bash $name");
die "Test interrupted, giving up" if ($? & 127) == 2;
return $r;
“这样,在触发CTRL+C时脚本确实会停止”-不,这样,在程序启动时脚本就会消失exec
仅在失败时返回。为什么要编写perl4样式的代码?现在已经不是1993年了;请严格使用代码>和使用警告
和不使用&
调用subs。另请参见和@melpomene,这是我已经剥离的一些遗留Perl脚本的一个片段。如果您不想硬编码2
,可以使用POSIX qw(SIGINT)
导入一个SIGINT
常量。另一个选项是使用fork
和exec
来启动子进程,而不是system
@salva我在system()
的描述中读到它相当于fork()
,exec()
和wait())
call.@TudorTimi这是system()
功能的大致概述。理解过程之间的关系就足够了。它忽略了信号处理等细节。salva评论的要点是,如果您自己实现一个类似于函数的system()
,您可以更改细节。
my $r = system("program.bash $name");
die "Test interrupted, giving up" if ($? & 127) == 2;
return $r;