Perl 在等待远程数据时读取STDIN;下载远程数据时终止

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

我有一个简单的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" };
}
当然,在
打印转储程序$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;