我有一个类似的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秒后超时)就跳到循环中的下一个项目?
答案 0 :(得分:4)
你遇到的问题是,当你运行curl
perl over over control并等待完成时。它会阻塞直到它完成。
所以这并不像看起来那么容易。
正如另一张海报所暗示的那样 - 您可以使用各种并行处理选项。我建议最简单的方法是不要使用'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
支持非阻塞检查)。
分叉 - 分叉子进程进行卷曲,如果按下某个键,则使用'main'进程发送信号。
IO::Select
这样您就不会对您的流程进行阻止读取。
答案 1 :(得分:2)
基本上你有两个选择:
<强> 1。使用线程
创建一个新线程,在那里调用所需的系统函数。等待输出。在另一个线程中,检查用户输入。在输入时,您可以终止子进程。子进程完成后,您可以忽略用户输入。
这样的解决方案似乎相当复杂,需要大量同步,可能使用信号。有风险的。
<强> 2。使用非阻塞IO
请阅读this帖子。它解释了如何从文件或管道进行非阻塞IO读取。您希望从管道(使用open
创建)进行非阻塞读取,然后从STDIN
进行无阻塞读取循环。
似乎是一种可行的方式,但是,唉,相当复杂。