我正在运行一个内部启动 bsub 作业的 perl 脚本。当我基于组 id 运行 perl 脚本时,当我在 unix 终端中按下控制 c 时,我想终止此 perl 脚本启动的所有作业。
请指教。
感谢和问候阿姆鲁塔
编辑:从评论中复制的代码
my $command = "bsub -q normal -g GROUPID <command>";
system($command);
尝试从 Ctrl-C 的信号处理程序SIGTERM
通过kill发送到进程组
$SIG{INT} = sub { kill 15, -$gpid }; # $gpid used in bsub command
这是否会奏效,以及如何可靠,取决于这些工作是什么和做什么的许多细节。
下面是一个进程如何(在不知不觉中)躲避子弹的示例,其中子进程更改了其进程组 ID。它这样做是为了演示向该组发送信号,但这也表明在向该组发送信号时存在漏洞。
一个例子
use warnings;
use strict;
use feature 'say';
my $pid;
$SIG{INT} = sub {
say "Got $_[0]. Send TERM to process group with $pid";
kill 15, -$pid;
};
$pid = fork // die "Can't fork: $!";
if ($pid == 0) {
$SIG{INT} = 'IGNORE';
setpgrp 0, $$;
say "\tChild's process group: ", getpgrp;
sleep 10;
say "\tkid done";
exit;
};
say "Parent $$ started $pid";
sleep 5;
sleep 3; # return to sleep after signal is handled
say "done";
当kill
被发送到否定的 PID(或带有否定信号)时,它会进入该进程组。在这里,我使用孩子的$pid
(要分配的)并在孩子中将其组 id 设置为那个($$
)。
由于分叉的进程继承了处理程序,因此信号也必须在子进程中处理。
几秒钟后按下Ctrl-C,输出为
父 10450 开始 10451 子进程组:10451 ^C得到 INT。发送 TERM 到组 10451 完毕
wheredone
在前一次打印后 3 秒打印。kid done
永远不会到来。
如果您希望父级也终止,exit
请在信号处理程序中添加一个或这样的。
如前所述,这可能会失败,因为孩子可以简单地更改其组。一种更可靠的方法是对可能被触发的作业进行编目,然后在运行时找到它们的 PID,从而终止它们。一个有用的工具是Proc::ProcessTable。这篇文章和这篇文章中有一些追捕过程的例子。