2011-12-09 26 views
6

Tôi có một tập lệnh perl chạy một loạt các tập lệnh batch để kiểm tra hồi quy. Tôi muốn thực hiện một thời gian chờ trên các kịch bản lô. Tôi hiện đang có mã sau đây.báo động perl với subprocess

my $pid = open CMD, "$cmd 2>&1 |"; 
    eval { 
       # setup the alarm 
       local $SIG{ALRM} = sub { die "alarm\n" }; 
       # alarm on the timeout 
       alarm $MAX_TIMEOUT; 
       log_output("setting alarm to $MAX_TIMEOUT\n"); 

       # run our exe 
       while(<CMD>) { 
         $$out_ref .= $_; 
       } 
       $timeRemaining = alarm 0; 
      }; 
      if ([email protected]) { 
        #catch the alarm, kill the executable 
      } 

Vấn đề là bất kể tôi đặt thời gian chờ tối đa là gì, báo thức không bao giờ bị vấp. Tôi đã thử sử dụng Perl :: Unsafe :: Signals nhưng điều đó không giúp được gì.

Đây có phải là cách tốt nhất để thực thi các tập lệnh theo lô nếu tôi muốn có thể nắm bắt đầu ra của chúng không? Có cách nào khác sẽ làm điều tương tự mà sẽ cho phép tôi sử dụng báo động, hoặc là có một phương pháp khác ngoài báo động để thời gian chờ chương trình?

Tôi đã xây dựng một kịch bản thử nghiệm để xác nhận rằng báo thức hoạt động với phiên bản perl và cửa sổ của tôi, nhưng nó không hoạt động khi tôi chạy một lệnh như thế này.

Tôi đang chạy ứng dụng này với activeperl 5.10.1 trên windows 7 x64.

Trả lời

4

Thật khó để biết khi nào alarm sẽ làm việc, khi một cuộc gọi hệ thống sẽ và sẽ không bị gián đoạn bởi một SIGALRM, làm thế nào cùng mã có thể cư xử khác nhau trên các hệ điều hành khác nhau, vv

Nếu lần công việc của bạn ra, bạn muốn giết các subprocess bạn đã bắt đầu. Đây là trường hợp sử dụng tốt cho báo động của người nghèo:

my $pid = open CMD, "$cmd 2>&1 |"; 
my $time = $MAX_TIMEOUT; 

my $poor_mans_alarm = "sleep 1,kill(0,$pid)||exit for 1..$time;kill -9,$pid"; 
if (fork() == 0) { 
    exec($^X, "-e", $poor_mans_alarm); 
    die "Poor man's alarm failed to start"; # shouldn't get here 
} 
# on Windows, instead of fork+exec, you can say 
# system 1, qq[$^X -e "$poor_mans_alarm"] 


... 

Báo thức của người đàn ông nghèo chạy trong một quy trình riêng biệt. Mỗi giây, nó kiểm tra xem quá trình với số nhận dạng $pid vẫn còn hoạt động hay không. Nếu quá trình không hoạt động, quá trình cảnh báo sẽ thoát. Nếu quá trình vẫn còn sống sau $time giây, nó sẽ gửi một tín hiệu giết cho quá trình (tôi sử dụng 9 để làm cho nó untrappable và -9 để đưa ra toàn bộ cây con xử lý, nhu cầu của bạn có thể thay đổi).

(thực tế có thể không cần thiết. Tôi sử dụng nó vì tôi cũng sử dụng thành ngữ này để theo dõi các quá trình có thể sống lâu hơn tập lệnh Perl đã khởi chạy chúng. Vì đó không phải là vấn đề với vấn đề này, bạn có thể bỏ qua các exec cuộc gọi và nói

if (fork() == 0) { 
    for (1..$time) { sleep 1; kill(0,$pid) || exit } 
    kill -9, $pid; 
    exit; 
} 

thay thế.)

Các vấn đề liên quan