Perl 在等待远程数据时读取STDIN;下载远程数据时终止
我有一个简单的perl脚本:Perl 在等待远程数据时读取STDIN;下载远程数据时终止,perl,concurrency,parallel-processing,stdin,Perl,Concurrency,Parallel Processing,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 $loc
#!/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" };
}
当然,在打印转储程序$localBookmarks
之后,会有5秒钟的静默
打印“本地书签”后,在等待“远程书签”时,是否可以立即阅读
?以防我知道本地书签是我这次所需要的全部(而且我不必等待几秒钟下载)。否则,当下载“远程书签”时,当前的
应该终止,下载的书签应该打印,并且-同样-在底部应该有
。perl是否可以做到这一点?有多种方法可以做到这一点。其中一个更明显的方法是生成一个线程来执行远程工作,在您阅读了STDIN之后,假设您在那里找不到答案,那么就加入该线程(以确保它完成)并在那里进行检查。该线程需要执行getRemoteBookmarks
中已有的所有操作,以及删除“选择书签”行(通常打印“\r”、“”x 60、“\r”
即可),打印出新组的转储程序,并打印出新的“选择书签”条目
如果已经做出选择,则需要额外的finnagling来阻止线程打印任何内容,在线程之间共享变量等等,但这是一般的想法
另一个选项是通过事件处理来处理此问题。基本上,您的输入(使用中的事件处理-请参阅了解如何使用各种事件模块)和ssh同时运行。这避免了一些线程共享,因为所有事情都发生在同一个线程中
无论哪种方式,您的脚本都将变得不那么简单,您最好在开始时打印“正在收集信息,请稍候”,收集所有选项(本地和远程),然后打印出选项。从成本/效益的角度来看,也就是说
祝你好运。下面是一个简单的示例,用于打开读取远程书签的单个子进程。当孩子完成后,它会将书签存储在一个文件中(另一种方法是使用线程、管道或文件句柄进行通信,但我认为这会使程序稍微复杂化)。当子进程终止时,父进程将获得一个
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 ($@) {
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 };
}
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 ($@) {
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 };
}
use strict;
use warnings;
use Storable qw(store);
sleep 5;
my $fn = 'bookmarks.dat';
store { d => "remote bookmark D", e => "remote bookmark E" }, $fn;