【问题标题】:Perl trapping Ctrl-C (sigint) in bashPerl 在 bash 中捕获 Ctrl-C (sigint)
【发布时间】:2011-11-22 15:53:45
【问题描述】:

我正在阅读 How do we capture CTRL ^ C - Perl Monks,但我似乎无法获得正确的信息来帮助解决我的问题。

问题是 - 我有一个无限循环,并且“多行”打印输出到终端(我知道我会被告知使用 ncurses 代替 - 但对于短脚本,我更舒服写一堆printfs)。我想以这样的方式捕获 Ctrl-C,脚本将仅在 此多行打印输出完成后终止。

脚本是(Ubuntu Linux 11.04):

#!/usr/bin/env perl
use strict;
use warnings;

use Time::HiRes;

binmode(STDIN);   # just in case
binmode(STDOUT);   # just in case


# to properly capture Ctrl-C - so we have all lines printed out
# unfortunately, none of this works:
my $toexit = 0;
$SIG{'INT'} = sub {print "EEEEE";  $toexit=1; };
#~ $SIG{INT} = sub {print "EEEEE";  $toexit=1; };
#~ sub REAPER { # http://www.perlmonks.org/?node_id=436492
        #~ my $waitedpid = wait;
        #~ # loathe sysV: it makes us not only reinstate
        #~ # the handler, but place it after the wait
        #~ $SIG{CHLD} = \&REAPER;
        #~ print "OOOOO";
    #~ }
#~ $SIG{CHLD} = \&REAPER;
#~ $SIG{'INT'} = 'IGNORE';



# main

# http://stackoverflow.com/questions/14118/how-can-i-test-stdin-without-blocking-in-perl
use IO::Select;
my $fsin = IO::Select->new();
$fsin->add(\*STDIN);


my ($cnt, $string);
$cnt=0;
$string = "";

while (1) {
  $string = ""; # also, re-initialize
  if ($fsin->can_read(0)) { # 0 timeout
    $string = <STDIN>;
  }
  $cnt += length($string);

  printf "cnt: %10d\n", $cnt;
  printf "cntA: %10d\n", $cnt+1;
  printf "cntB: %10d\n", $cnt+2;
  print "\033[3A"; # in bash - go three lines up
  print "\033[1;35m"; # in bash - add some color
  if ($toexit) { die "Exiting\n" ; } ;
}

现在,如果我运行它并按下 Ctrl-C,我会得到类似这样的结果(注意,_ 表示脚本终止后终端光标的位置): p>

MYPROMPT$ ./test.pl
cnEEEEEcnt:          0
MYPROMPT$ _
cntB:          2
Exiting

或:

MYPROMPT$ ./test.pl
cncnt:          0
MYPROMPT$ _
cntB:          2
Exiting

...但是,我想得到:

MYPROMPT$ ./test.pl
cncnt:          0
cntA:          1
cntB:          2
Exiting
MYPROMPT$ _

显然,处理程序正在运行 - 但不是完全按照我期望的时间(或顺序)运行。有人可以澄清我该如何解决这个问题,以便得到我想要的输出吗?

非常感谢您的任何回答, 干杯!

【问题讨论】:

  • 当它出现在控制流中的唯一位置是在将光标带回的代码之后,我不确定你怎么能期望在三个 cnt 行下面有“退出”顶部。
  • 感谢@JB 的评论 - 刚刚意识到这是问题所在 :) 干杯!

标签: bash perl signals sigint bash-trap


【解决方案1】:

嗯...似乎解决方案比我想象的要容易:) 基本上,“被困出口”的检查应该在打印行之后运行 - 但在打印“向上三行”的字符之前;也就是说,该部分应该是:

  printf "cnt: %10d\n", $cnt;
  printf "cntA: %10d\n", $cnt+1;
  printf "cntB: %10d\n", $cnt+2;
  if ($toexit) { die "Exiting\n" ; } ;
  print "\033[3A"; # in bash - go three lines up
  print "\033[1;35m"; # in bash - add some color

... 然后 Ctrl-C 上的输出似乎是:

MYPROMPT$ ./test.pl 
cnt:          0
^CcntA:          1
cntB:          2
Exiting
MYPROMPT$  _

嗯,希望这可以帮助别人,
干杯!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多