我正在尝试使用Perl system
调用在终端窗口中将Emacs作为前台进程运行。当我在终端窗口中按CTRL-C
时,我想终止Emacs和Perl脚本。但是,只有Emacs命令终止。这是一个示例脚本test.pl
:
#! /usr/bin/env perl
use strict;
use warnings;
my $cmd = shift;
for ( my $i = 1; $i <= 3; $i ++) {
my $res = system ($cmd);
if ( $res == -1 ) {
die "Failed to execute '$cmd': $!\n";
}
my $signal = ($? & 127);
my $exit_code = ($? >> 8);
print "exit_code = $exit_code, signal = $signal\n";
if ( $signal ) {
die "Command '$cmd' died with signal $signal\n";
}
}
的输出
$ test.pl 'emacs file.txt'
是(按CTRL-C
三次后):
^ Cexit_code = 0,信号= 0
^ Cexit_code = 0,信号= 0
^ Cexit_code = 0,signal = 0
所以Emacs终止了,但Perl脚本一直在运行.. 但是,如果我跑
$ test.pl 'sleep 10'
我得到输出:
^ Cexit_code = 0,信号= 2
命令&#39;睡10&#39;死于信号2
因此,如果我运行sleep 10
而非emacs file.txt
,则可以正常运行。
答案 0 :(得分:1)
您的代码错误地假设您将执行的命令将捕获INT信号,然后使用约定(128 *&#34;退出状态&#34;)+ signum设置其退出代码。
对于睡眠来说这是真的,但对于许多其他程序来说却是假的。
但是你可以用你想要的任何命令的方式构建一个包装器。这将是一个仅用于处理Control-C的emacs包装器:
#!/bin/bash -e
trap "exit 130" INT
emacs "$@"
只需将它放在您的路径中并在您的perl代码中执行它,而不是emacs。将其扩展为其他信号是微不足道的。虽然它对我有用,但似乎这个版本适合你:
#!/bin/bash -e
emacs "$@"
另一个解决方案是使用perl工具来处理子进程
答案 1 :(得分:0)
您可以使用IPC::Open2
将Emacs作为子进程运行。然后使用Perl脚本中的waitpid
等待子进程。如果Perl脚本(父级)获得SIGINT信号,则子级也将收到SIGINT信号。所以以下似乎有效:
use strict;
use warnings;
use IPC::Open2;
my $cmd = shift;
$SIG{INT} = sub { die "Parent got SIGINT\n" };
for ( my $i = 1; $i <= 3; $i ++) {
print "i = $i\n";
my ($chld_out, $chld_in);
my $pid = open2($chld_out, $chld_in, $cmd);
waitpid($pid, 0);
}
<强>参考文献:强>