Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux CTRL+;C和Perl';s system()函数-脚本未被中断_Linux_Perl - Fatal编程技术网

Linux CTRL+;C和Perl';s system()函数-脚本未被中断

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"); }

我有一个Perl脚本,它使用
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;