繁体   English   中英

如何在Perl脚本中从Emacs提取SIGINT信号?

[英]How to pick up SIGINT signal from Emacs in Perl script?

我试图使用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 3次后):

^ Cexit_code = 0,信号= 0
^ Cexit_code = 0,信号= 0
^ Cexit_code = 0,信号= 0

因此Emacs被终止,但是Perl脚本继续运行。但是,如果我运行

$ test.pl 'sleep 10'

我得到输出:

^ Cexit_code = 0,信号= 2
命令“ sleep 10”死于信号2

因此,如果我运行sleep 10而不是emacs file.txt它可以正常工作。

您的代码错误地假定您将执行的命令将捕获INT信号,然后使用(128 *“退出状态”)+信号的约定设置退出代码。

对于睡眠而言,这是正确的,但对于许多其他程序而言,则是错误的。

但是,您可以使用对任何所需命令都适用的方式构建包装器。 这将是仅用于处理Control-C的emacs包装器:

#!/bin/bash -e
trap "exit 130" INT
emacs "$@"

只需将其放在您的路径中,然后在perl代码(而不是emacs)中执行它即可。 将其扩展为其他信号是微不足道的。 虽然对我有用,但似乎此版本对您有用:

#!/bin/bash -e
emacs "$@"

另一个解决方案是使用perl工具来处理子流程

您可以使用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);
}

参考文献:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM