【问题标题】:CTRL+C and Perl's system() function - script not getting interruptedCTRL+C 和 Perl 的 system() 函数 - 脚本不会被中断
【发布时间】:2021-06-19 19:36:47
【问题描述】:

我有一个 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");

这是外部“程序”:

#!/bin/env bash

echo "Started $1"
sleep 3
echo "Finished $1"

我启动了脚本并发出了 CTRL + Z。然后我做了一个ps -o pid,pgrp,cmd 来列出进程信息。我可以看到脚本、它调用的 bash shell 和 sleep 命令都属于同一个进程组。虽然sleep 正在执行,但我也希望它是前台进程组。我在 Linux、信号和终端上阅读了一些内容,发现 CTRL + C 应该向整个前台进程组发送中断,从而也终止脚本。

我也尝试过使用exec() 而不是system()。这样脚本在触发 CTRL + C 时确实会停止,但不会通过 test1

谁能解释一下这里发生了什么?

【问题讨论】:

标签: linux perl


【解决方案1】:

很高兴您已经调查并了解了流程组。解释这些通常是此类问题的难点。所以你知道中断信号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;
}

例如,您可以在 run_the_test 中执行此操作:

my $r = system("program.bash $name");
die "Test interrupted, giving up" if ($? & 127) == 2;
return $r;

【讨论】:

  • 如果你不想硬编码2,你可以use POSIX qw(SIGINT);导入一个SIGINT常量。
  • 另一种选择是使用forkexec 来启动子进程而不是system
  • @salva 我在system() 的描述中读到它相当于fork()exec()wait() 调用。
  • @TudorTimi 这是system() 所做工作的大致轮廓。了解流程之间的关系就足够了。它省略了信号操作等细节。萨尔瓦评论的重点是,如果你自己实现了一个system()-like 函数,你可以更改细节。
【解决方案2】:

有类似的问题,使用系统和管道。 CTRL-C 不起作用。 以下解决了它:

使用 sigtrap qw/die normal-signals/;

【讨论】:

    猜你喜欢
    • 2021-12-15
    • 1970-01-01
    • 2020-07-08
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多