2011-09-22 124 views
1

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

事情是 - 我有一个无限循环,并且'多行'打印输出到终端(我知道我会被告知使用ncurses而不是 - 但对于简短脚本,我更舒适写一堆printf s)。我想以这种方式捕捉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,我要么得到这样的事情(说明,_显示终端的位置游标脚本已经终止后):

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$ _ 

显然,处理程序正在运行 - 但并不完全在时序(或订单),我希望他们。有人可以澄清我如何解决这个问题,所以我得到我想要的输出?

非常感谢任何答案, 干杯!

+1

我不确定如果在控制流中出现的唯一位置恰好在将光标移回顶端的代码之后,您可能期望在三个“cnt”行下面有“退出”。 –

+0

感谢您的评论@JB - 刚刚意识到这是问题:)干杯! – sdaau

回答

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$ _ 

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