我目前有一個Perl腳本,它在系統上運行一個外部命令,收集輸出,並根據返回的內容執行一些操作。現在,這裏是我如何運行這個(其中$ cmd是用命令設置一個字符串):如何以異步方式在Perl中運行系統命令?
@output = `$cmd`;
我想改變這種做法,如果命令掛起,不經過這麼多的返回值那麼我會殺死這個命令。我將如何去異步運行它?
我目前有一個Perl腳本,它在系統上運行一個外部命令,收集輸出,並根據返回的內容執行一些操作。現在,這裏是我如何運行這個(其中$ cmd是用命令設置一個字符串):如何以異步方式在Perl中運行系統命令?
@output = `$cmd`;
我想改變這種做法,如果命令掛起,不經過這麼多的返回值那麼我會殺死這個命令。我將如何去異步運行它?
如果你真的只需要在給定的系統調用上放一個超時,這是一個比異步編程簡單得多的問題。
所有你需要的是一個eval()塊內部的alarm()。
下面是一個示例代碼塊,它將這些代碼放入可以放入代碼的子例程中。該示例調用睡眠等都不是令人興奮的輸出,但不告訴你,你有興趣的超時功能,運行它的 輸出爲:
/斌/睡眠2失敗:超時在 ./time退房手續線15
$ cat time-out
#!/usr/bin/perl
use warnings;
use strict;
my $timeout = 1;
my @cmd = qw(/bin/sleep 2);
my $response = timeout_command($timeout, @cmd);
print "$response\n" if (defined $response);
sub timeout_command {
my $timeout = (shift);
my @command = @_;
undef [email protected];
my $return = eval {
local($SIG{ALRM}) = sub {die "timeout";};
alarm($timeout);
my $response;
open(CMD, '-|', @command) || die "couldn't run @command: $!\n";
while(<CMD>) {
$response .= $_;
}
close(CMD) || die "Couldn't close execution of @command: $!\n";
$response;
};
alarm(0);
if ([email protected]) {
warn "@cmd failure: [email protected]\n";
}
return $return;
}
有辦法做到這一點很多:
在Win32系統當心破'select'只用於插座和與控制檯窗口可能奇怪反應工程,wperl(運行在一個非控制檯窗口的方式perl的,但對STDIO和子進程有奇怪的影響)。在好的一面,你可以做一個'system(-1,'foo')'。此外,運行64個子項後,某些啓動進程的方式失敗。 IME,'Win32 :: Process :: Create()'是在bgrnd中運行程序最安全的方法。 – daotoad 2009-11-18 01:10:24
@daotoad,感謝您的評論。我缺乏win32線索表明我唯一知道的是fork()是用線程模擬的,而且你不能使用警報。我猜如果涉及win32,IPC :: Cmd將是一個不錯的選擇。 – tsee 2009-11-18 08:46:00
如果你的外部程序不帶任何輸入,尋找在perlipc
手冊頁下面的話:
這裏是一個安全的反引號或管開放閱讀:
使用示例代碼並警告它(這也在perlipc
中解釋)。
謝謝,這是我所尋找的更多。 – Joel 2009-12-03 16:10:59
我認爲你需要在死信息中有一個\ n。 (http://perldoc.perl.org/functions/alarm.html) – ddoxey 2013-04-04 05:04:16