我有一个像这样的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
进行非阻塞读取
这似乎是一条路,但是,唉,也相当复杂。