2009-08-01 24 views
16

Tôi đang sử dụng IO.popen trong Ruby để chạy một loạt các lệnh dòng lệnh trong một vòng lặp. Sau đó, tôi cần phải chạy một lệnh khác bên ngoài vòng lặp. Lệnh bên ngoài vòng lặp không thể chạy cho đến khi tất cả các lệnh trong vòng lặp kết thúc.Làm thế nào để chờ quá trình kết thúc bằng IO.popen?

Làm cách nào để chương trình chờ điều này xảy ra? Hiện tại lệnh cuối cùng đang chạy quá sớm.

Một ví dụ:

for foo in bar 
    IO.popen(cmd_foo) 
end 
IO.popen(another_cmd) 

Vì vậy, tất cả cmd_foos cần phải trả lại trước khi another_cmd được chạy.

Trả lời

4

Tôi nghĩ bạn cần phải chỉ định kết quả từ các cuộc gọi IO.popen trong chu kỳ tới các biến và tiếp tục gọi read() trên chúng cho đến khi eof() trở thành sự thật.

Sau đó, bạn biết rằng tất cả các chương trình đã hoàn thành quá trình thực thi và bạn có thể bắt đầu another_cmd.

+2

Cũng giống như một lưu ý thêm: sử dụng biểu mẫu khối phương pháp IO là thường an toàn hơn. Ngoài ra, trong 1,9 bạn nhận được thêm mạnh mẽ bởi vì các biến khối có phạm vi khác nhau mà ngăn ngừa sửa đổi cùng một biến được đặt tên bên ngoài khối (và bạn sẽ kiếm được một cảnh báo). –

6
for foo in bar 
    out = IO.popen(cmd_foo) 
    out.readlines 
end 
IO.popen(another_cmd) 

Đọc đầu ra cho biến sau đó gọi out.readlines. Tôi nghĩ rằng out.readlines phải chờ quá trình kết thúc trước khi nó trở lại.

Ghi có cho Andrew Y để chỉ cho tôi đúng hướng.

+0

Tôi đã thử chính xác điều tương tự và kết thúc với thây ma (không tồn tại), vì vậy không lý tưởng – nhed

+0

Nó bị thiếu ngoài.close –

3

tôi đề nghị bạn sử dụng Thread.join để đồng bộ hóa các popen cuộc gọi cuối cùng:

t = Thread.new do 
    for foo in bar 
     IO.popen(cmd_foo) 
    end 
end 

t.join 

IO.popen(another_cmd) 
1

Bạn có cần đầu ra của popen? Nếu không, bạn có muốn sử dụng Kernel#system hoặc một số lệnh khác không?

18

Sử dụng các hình thức ngăn chặn và đọc tất cả các nội dung:

IO.popen "cmd" do |io| 
    # 1 array 
    io.readlines 

    # alternative, 1 big String 
    io.read 

    # or, if you have to do something with the output 
    io.each do |line| 
    puts line 
    end 

    # if you just want to ignore the output, I'd do 
    io.each {||} 
end 

Nếu bạn không đọc được đầu ra, nó có thể là khối xử lý vì các đường ống kết nối quá trình khác và quá trình của bạn là đầy đủ và không ai đọc từ nó.

+0

Sẽ 'IO.popen ('cmd'). Close' làm việc khi loại bỏ stdout? Tài liệu nói rằng nó đặt '$?' (Do đó chờ đợi), nhưng tôi không rõ ràng nó cũng loại bỏ tất cả stdout mà không bị chặn. –

+0

Chính xác bạn có ý gì khi "loại bỏ stdout"? Mã bạn hiển thị không hủy bất kỳ thứ gì. Nếu bạn chỉ muốn thực hiện một cái gì đó và không làm bất cứ điều gì đặc biệt với hệ thống đầu ra() là thích hợp hơn, –

+0

bằng cách "loại bỏ stdout" tôi có nghĩa là "đọc đầu ra", mà câu trả lời này có thể được yêu cầu để ngăn chặn chặn. –

16

Rõ ràng canonical way để làm điều này là:

Process.wait(popened_io.pid) 
+0

Câu trả lời này là chính xác nhất. Không có tác dụng phụ (như với io.read), và rất rõ ràng những gì nó đang làm. – siannopollo

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