Perl:在完成执行之前,在循环中移动到下一个项目



我有一个像这样的perl脚本:

foreach my $addr ('http://site1.com', ...., 'http://site2.com') {
    my $script = `curl -m 15 $addr`;
    *do stuff with $script*
} 

-m将超时设置为 15 秒。有没有办法做到这一点,如果用户按下一个键,它停止当前执行并移动到foreach中的下一个项目?我知道last;可以移动到下一项,但我不确定如何将其链接到正在推送的键以及如何在 curl 脚本运行时执行此操作

编辑:因此,根据答案,在curl运行时似乎很难做到这一点。是否可以在 curl 运行时按下一个键,并在 curl 脚本返回后立即跳到循环中的下一项(或在 15 秒超时)?

你遇到的问题是,当你运行curl perl时,它会交出控制权并等待完成。它会阻止,直到"完成"。

因此,要做到这一点并不像看起来那么容易。

正如另一张海报所暗示的那样 - 您可以使用各种并行处理选项。我建议最简单的方法是放弃使用"any"键,并需要ctrl-c。

所以你会做:

foreach my $addr ('http://site1.com', ...., 'http://site2.com') {
     my $pid = open ( my $curl_fh, "-|", "curl -m 15 $addr" );
     $SIG{'INT'} = sub { print "Aborting fetch of $addr"; kill $pid };
     while ( <$curl_fh> ) {
         print;
     }
     #might want to set it to something else. 
     #undef means 'ctrl-c' will abort the whole program. 
     #IGNORE means exactly what it says on the tin.
     #important to change it though, as it has a specific pid it'll kill, 
     #and that might cause problems. 
     $SIG{'INT'} = undef;
} 

这样做是配置SIGINT(例如ctrl-c),这样它就不会杀死你的程序,但会杀死子进程。

如果您想查看其他选项,我会提供:

    多线程,
  • 生成一个线程以在后台"执行"卷曲获取,并使用Thread::Queue来回传递结果。(Thread::Queue支持非阻塞检查)。

  • 分叉 - 分叉一个子进程来执行 curl,并在按下键时使用您的"主"进程发送信号。

  • IO::Select这样您就不会对进程进行阻塞读取。

基本上你有两个选择:

1. 使用线程

创建一个新线程,在那里调用所需的系统函数。等待输出。在另一个线程中,检查用户输入。在输入时,您可以终止子进程。子进程完成后,可以忽略用户输入。

这样的解决方案似乎相当复杂,需要大量同步,可能使用信号。危險。

2. 使用非阻塞 IO

请阅读此线程。它说明了如何从文件或管道进行非阻塞 IO 读取。您希望从管道进行非阻塞读取(使用 open 创建),然后从 STDIN 进行非阻塞读取

,循环。

这似乎是一条路,但是,唉,也相当复杂。

最新更新