2016-09-03 10 views
2

をダウンロードされたときに終了します。リモートデータを待つ間にSTDINを読み取ります。リモートデータは、私は簡単なperlスクリプトを持って

#!/usr/bin/env perl 

use strict; 
use Data::Dumper; 
use utf8; 
binmode(STDOUT, ":utf8"); 
$|++; 

my $localBookmarks = { 
    a => "local bookmark A", 
    b => "local bookmark B", 
    c => "local bookmark C", 
}; 
print Dumper $localBookmarks; 

my $remoteBookmarks = getRemoteBookmarks(); 
print Dumper $remoteBookmarks; 

print "choose a bookmark: "; 
my $answer = <STDIN>; 
print "You want: $answer"; 
# process $answer... 

sub getRemoteBookmarks 
{ 
    # Net::SSH::Perl connection; exec command; parse it; return it 
    # lets just simulate this 
    sleep(5); 
    return { d => "remote bookmark D", e => "remote bookmark E" }; 
} 

出力は次のようになります。もちろん

$ perl test.pl 
$VAR1 = { 
      'b' => 'local bookmark B', 
      'a' => 'local bookmark A', 
      'c' => 'local bookmark C' 
     }; 
$VAR1 = { 
      'd' => 'remote bookmark D', 
      'e' => 'remote bookmark E' 
     }; 
choose a bookmark: 

5秒間沈黙があるprint Dumper $localBookmarks後。

"リモートブックマーク"を待っている間に "ローカルブックマーク"を印刷した直後に<STDIN>を読むことはできますか?ローカルのブックマークがすべて私がこの時間を必要としていることを知っている場合(そして私はダウンロードのために数秒待つ必要はありません)。それ以外の場合、「リモートブックマーク」がダウンロードされると、現在の<STDIN>は終了され、ダウンロードされたブックマークが印刷され、最後に - <STDIN>になるはずです。これはperlで可能ですか?

答えて

3

これを行うにはいくつかの方法があります。より明白な方法の1つは、リモート作業を行うためのスレッドを生成し、STDINから読み込んだ後にそこで答えを見つけることができないと仮定して、スレッドに参加して(完了したことを確認するため)、そこにチェックを入れます。スレッドでは、すでにであるすべてのことを行う必要があります。また、「ブックマークの選択」行(普通は"\r", ' ' x 60, "\r"で十分です)を消去し、新しいグループのダンパーを印刷し、新しい「ブックマークを選択してください"エントリ。

選択肢が既に作成されていてスレッドがスレッド間で変数を共有しているなどの理由で、スレッドに何も印刷されないようにするには、少しの余分なスレッドが必要ですが、それは一般的な考えです。

イベント処理によってこれを処理することもできます。あなたは基本的に両方の入力を持っています(Term::ReadLineでのイベント処理を使用します - さまざまなイベントモジュールでこれを行う方法はTerm::ReadLine::Eventを参照してください)。同時にsshが実行されます。これが避けているのは、同じスレッドですべてが起こっているので、スレッドの共有などです。

どちらの方法でも、スクリプトはずっと簡単ではなく、最初は「情報を収集してお待ちください」を印刷して、ローカルとリモートのすべてのオプションをすべて収集してください。オプションを印刷します。コスト/利益の観点からは、それはです。

幸運。

2

IPC::Open3を使用して、リモートブックマークを読み取る1つの子プロセスを開く単純な例を示します。子が終了するとブックマークはファイルに保存されます(スレッド、パイプ、ファイルハンドルを使って通信することもできますが、プログラムが少し複雑になると思います)。子プロセスが終了すると、親プロセスはCHLDシグナルを受け取ります。これにより、親プロセスは入力ループを終了し、ディスクからリモートブックマークを読み込みます。

use feature qw(say); 
use strict; 
use warnings; 
use Data::Dumper; 
use IPC::Open3; 
use Symbol qw(gensym); 
use Storable qw(retrieve); 

local $SIG{CHLD} = sub { 
    die "\nBackground process finished..\n"; 
}; 

my $child1 = start_reading_remote_bookmarks(); 
my $local_bookmarks = { 
    a => "local bookmark A", 
    b => "local bookmark B", 
    c => "local bookmark C", 
}; 
print Dumper $local_bookmarks; 
eval { 
    run_input_loop(); 
}; 
if ([email protected]) { 
    print "\n"; 
    my $remote_bookmarks = retrieve('bookmarks.dat'); 
    print Dumper $remote_bookmarks; 
    run_input_loop(); 
} 

sub run_input_loop { 
    while (1) { 
     print "Choose a bookmark: "; 
     chomp(my $answer = <STDIN>); 
     say "You want: $answer"; 
     # process $answer... 
    } 
} 

sub start_reading_remote_bookmarks { 
    my $cmd = 'get_bookmarks.pl'; 
    my $cherr = gensym; 
    my $pid = open3(my $chin, my $chout, $cherr, $cmd); 
    return { pid => $pid, kid_in => $chin, kid_out => $chout, kid_err => $cherr }; 
} 

get_bookmarks.pl

use strict; 
use warnings; 
use Storable qw(store); 

sleep 5; 
my $fn = 'bookmarks.dat'; 
store { d => "remote bookmark D", e => "remote bookmark E" }, $fn; 
ある:次いで、親は、入力されたループに再び入ります
関連する問題