问题
I'm reading How do we capture CTRL ^ C - Perl Monks, but I cannot seem to get the right info to help with my problem.
The thing is - I have an infinite loop, and 'multiline' printout to terminal (I'm aware I'll be told to use ncurses
instead - but for short scripts, I'm more comfortable writing a bunch of printf
s). I'd like to trap Ctrl-C in such a way, that the script will terminate only after this multiline printout has finished.
The script is (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" ; } ;
}
Now, if I run this, and I press Ctrl-C, I either get something like this (note, the _
indicates position of terminal cursor after script has terminated):
MYPROMPT$ ./test.pl
cnEEEEEcnt: 0
MYPROMPT$ _
cntB: 2
Exiting
or:
MYPROMPT$ ./test.pl
cncnt: 0
MYPROMPT$ _
cntB: 2
Exiting
... however, I'd like to get:
MYPROMPT$ ./test.pl
cncnt: 0
cntA: 1
cntB: 2
Exiting
MYPROMPT$ _
Obviously, handlers are running - but not quite in the timing (or order) I expect them to. Can someone clarify how do I fix this, so I get the output I want?
Many thanks in advance for any answers, Cheers!
回答1:
Hmmm... seems solution was easier than I thought :) Basically, the check for "trapped exit" should run after the lines are printed - but before the characters for "go three lines up" are printed; that is, that section should be:
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
... and then the output upon Ctrl-C seems to be like:
MYPROMPT$ ./test.pl
cnt: 0
^CcntA: 1
cntB: 2
Exiting
MYPROMPT$ _
Well, hope this may help someone,
Cheers!
来源:https://stackoverflow.com/questions/7512317/perl-trapping-ctrl-c-sigint-in-bash