2014-10-14 1 views
0

Во-первых, я знаю, что этот вопрос задавали много раз, но никакого решения здесь нет, кажется, помогает мне:/Захват выходной сценарий оболочки должным образом в Perl

Я пытаюсь сделать интерфейс в Perl, который может запустить некоторую оболочку скрипты.

Моя идея состояла в том, чтобы получить вывод сценария оболочки (stdout и stderr) и показать его в прямом эфире на другом кадре в главном окне.

Проблема:

Выход не сохраняется в переменной, это показать немедленно на середине экрана, и я не понимаю, это поведение ..

Вот небольшой скриншот результат:

-deleted-

цель состоит в том, чтобы показать выход в кадре «Прогресс»; Я пробовал много методов Perl, чтобы это работало, но я не каждый раз, когда ...

Вот некоторые примеры того, что я пробовал:

sub launch_child(@) 
{ 
    my $pid = open(KID, '-|'); 
    die "fork: $!" unless defined($pid); 
    if($pid) { 
     my $output; 
     while (<KID>) { 
      $process_tracking->text($process_tracking->text() . "$_"); 
     } 
     close(KID); 
    } else { 
     exec @_; 
    } 
} 

или

sub launch_child() 
{ 
    my $sel = IO::Select->new(); 
    open my $fh, '-|', './shell_script.sh'; 
    while (<$fh>) { 
     $process_tracking->text($process_tracking->text() . "$_"); 
    } 
    close $fh; 
    $sel->add($fh); 
    push(@selects , $sel); 
} 

Спасибо всем Perl специалисты, которые могут помочь мне достичь этого;)

EDIT:

я найти способ сделать это (спасибо choroba за "Stderr" ключ):

my @selects =(); 

sub launch_child() 
{ 
    my $sel = IO::Select->new(); 
    open my $fh, '-|', './shell_script.sh 2>&1'; 
    $sel->add($fh); 
    push(@selects , $sel); 
} 
sub read_from_child() 
{ 
    if (scalar @selects > 0) { 
     for my $sel (@selects) { 
      if (my @readers = $sel->can_read(0)) { 
       for my $fh (@readers) { 
        my $rv = sysread($fh, my $buf, 64*1024); 
        if (!$rv) { 
         $sel->remove($fh); 
         close($fh); 
         next; 
        } 
        $process_tracking->text($process_tracking->text().$buf); 
        $process_tracking->cursor_to_end(); 
       } 
      } 
     } 
    } 
} 

while (1) { 
    $cui->{-read_timeout} = 0; 
    $cui->do_one_event(); 
    read_from_child(); 
    sleep 0.1; 
} 

снимок экрана нового результата:

-deleted-

Теперь я 'спрашивает, почему цвета в сценарии оболочки не оцениваются: echo -ne [...]

ответ

1

Вы правильно читаете STDOUT процесса, но STDERR свободно идет прямо на экран. См. perlipc.

+0

Не уверен, что понимать, что делать exaccty ... Но я пытаюсь перенаправить STDERR в STDOUT, он работает, но, похоже, он заполняет буфер, прежде чем писать что-либо; Я пишу «$ | = 1», но ничего не меняет:/ – Doubidou

+0

@Doubidou: Что вы подразумеваете под «заполнением буфера»? – choroba

+0

Я имею в виду, он ждет, пока весь сценарий оболочки не будет выполнен, прежде чем показывать что-либо; но всего лишь секунду назад я нашел метод, отправив $ fh в IO: Select и выполнив отдельный цикл, который читает Select; он работает :) Ужасно, бут-тит работает ... Теперь мне нужно выяснить, почему цвета ANSI моего сценария оболочки не оцениваются в скрипте Perl. – Doubidou

Смежные вопросы