2017-01-20 2 views
3

Я написал простой скрипт для управления временем загрузки (начало и конец) с wget в Linux-Gnu с Perl. Нет проблем, и все работает хорошо, за исключением того, что я хочу Я могу прочитать ключ с клавиатуры, когда процесс запущен.
Я показываю простую анимацию движения на экране, которую я не хочу останавливать, а затем читать ключ.чтение ключа с клавиатуры при запуске процесса

, например, как MPlayer или MPV, что при запуске на Comman линии, вы можете нажать q для выхода или s, чтобы сделать снимок с экрана.

Часть сценария:

do { 
    system("clear"); 
    ($h, $m, $s) = k5mt::second_to_clock( $till_shutdown); 

    set_screen(); 
    set_screen(24); 

    set_screen(); 
    say "download was started ..."; 

    set_screen(); 
    set_screen(24); 

    set_screen(); 
    printf "till finish: %02d %02d %02d\n", $h, $m, $s; 

    set_screen(); 
    set_screen(24); 

    set_screen(); 
    say "wget pid: [$wget_pid]"; 

    set_screen(); 
    set_screen(24); 

    set_screen(); 
    $waiting_temp .= $animation[ $counter_animation++ ]; 
    say $waiting_temp; 
    if(length($waiting) == $counter_animation){ 
     $waiting_temp = ""; 
     $counter_animation = 0; 
    } 

    set_screen(); 
    set_screen(24); 

    sleep 1; 
    $till_shutdown--; 

} while($till_shutdown); 

enter image description here

слова ждут до конца ..... показан последовательно (без перерыва), и я хочу, чтобы прочитать ключ как q для выхода из программы.

UPDATE

Я ищу решение с, как многие опции, как я хочу, если я хотел только для выхода из программы я просто сказать пользователю нажать Ctrl + C

Можно с помощью скриптов в Perl? или нет? Если да, то как?

Примечание: если это возможно без каких-либо модулей, скажите, пожалуйста, решение без какого-либо модуля, и если нет, то все в порядке не проблема

Однако, спасибо так много.

+0

Одно решения, которое я вижу в создании подпроцесса и сделать основную задачу в то время как родитель будет продолжать искать вход, если пользователь вводит д, то родитель будет убивать суб proccess –

+0

@PrashantPokhriyal Ваш смысл в том, что я использую 'fork()' для чтения 'key'? –

+0

Да Создайте fork –

ответ

-1

Это будет работать для вас

use 5.010; 
use strict; 
use Term::ReadKey; 

ReadMode 4; # It will turn off controls keys (eg. Ctrl+c) 

my $key; 

# It will create a child so from here two processes will run. 
# So for parent process fork() will return child process id 
# And for child process fork() will return 0 id 

my $pid = fork(); 

# This if block will execute by the child process and not by 
# parent because for child $pid is 0  

if(not $pid){ 

    while(1){ 

     # Do your main task here 
     say "hi I'm sub process and contains the main task"; 
     sleep 2; 
    } 
} 

# Parent will skip if block and will follow the following code 
while (1) { 

    $key = ReadKey(-1); # ReadKey(-1) will perform a non-blocked read 

    if($key eq 'q'){ # if key pressed is 'q' 

     `kill -9 $pid`; # then if will run shell command kill and kill 
         # the child process 
     ReadMode 0;  # Restore original settings for tty. 

     exit;   # Finally exit from script 

    } elsif($key eq 'h') { 

     say "Hey! you pressed $key key for help"; 
    } elsif($key ne '') { 

     say "Hey! You pressed $key"; 
    } 
} 

Для Term :: ReadKey Документация ---->Term::ReadKey

Для лучшего понимания разветвление в Perl ----->Fork in Perl

+0

Пожалуйста, объясните, как это работает. –

+0

@ k-five Я отредактировал свой ответ. Надеюсь, это поможет вам –

+0

У меня есть сомнения, что он может управлять более чем «одним ключом» или нет. И я вижу, что во втором не может быть больше одного ключа, а (1), правильно ли я или нет? –

-1

Если вы не беспокоитесь о небольшой задержке, вы можете играть с select и alarm, чтобы попытаться обработать пользовательский ввод.

С помощью select вы можете обрабатывать STDIN и использовать alarm, вы можете подождать несколько секунд или меньше для ввода пользователем.

#!/usr/bin/env perl 

use common::sense; 

use IO::Select; 

my $sel = IO::Select->new(); 
$sel->add(\*STDIN); 

$|++; 

my $running = 1; 

while ($running) { 

    eval { 

     local $SIG{ALRM} = sub { die 'Time Out'; }; 

     alarm 0.5; 

     if ($sel->can_read(0)) { 

      my $input = <STDIN>; 

      chomp $input; 

      print "STDIN > $input\n"; 

      $running = 0; 

     } 
    }; 

    if ([email protected]) { 

     select(undef, undef, undef, 0.5); 

     print "."; 

    } 
} 

print "\nEnd Of Script\n"; 

Я сказал вам, чтобы попытаться использовать Term :: ReadKey :-)

Здесь мы идем:

!/usr/bin/env perl 

use common::sense; 
use Term::ReadKey; 

my $running = 1; 
my $key; 

while ($running) { 
    ReadMode 4; # Turn off controls keys 
    while (not defined($key = ReadKey(-1))) { 

     select(undef, undef, undef, 0.5); 

     print '.'; 

    } 
    print "\nSTDIN> $key\n"; 
    ReadMode 0; 

} 

print "\nEnd Of Script\n"; 

Теперь вы просто должны обрабатывать сигналы, как бросить курить или INT, чтобы выйти из но с помощью этого вы можете захватить вход и делать все, что хотите.

+0

Конечно, я РАБОТАЛ, это нехорошее решение, спасибо, хотя за попытку –

+0

@ k-five Я просто добавил что-то, что может работает – carlosn

+0

вот ваш комментарий: ** Вы пытались использовать Term :: ReadLine **, вы сказали использовать ** Readline ** –

2

Предполагая, что ваша программа имеет центральный цикл, или если вы можете просто вставить проверки клавиатуры в обработку, вам лучше использовать Term::ReadKey, чем пытаться поместиться в fork и обрабатывать необходимые межпроцессные коммуникации катион

Вызов ReadKey(-1) будет выполнять неблокирующее чтение, которое будет возвращать один символ, если был удален ключ, или undef. (Вы можете указать второй параметр, который будет использоваться IO-каналом, но по умолчанию будет использоваться STDIN.)

Предлагаю вам запустить этот пример. Я использовал sleep 1 как манекен для обработки контура

use strict; 
use warnings 'all'; 
use feature 'say'; 

use Term::ReadKey; 

my $n; 

while() { 

    my $key = ReadKey(-1); 

    say "key $key entered" if defined $key; 

    sleep 1; 

    say ++$n; 
}