2009-04-30 21 views
22

Tôi có một quy trình chạy dài và tôi cần nó để khởi chạy một quy trình khác (quá trình này sẽ chạy trong một thời gian tốt). Tôi chỉ cần bắt đầu nó, và sau đó hoàn toàn quên nó đi.Làm thế nào để bắn và quên một tiến trình con?

Tôi quản lý để làm những gì tôi cần bằng cách lấy một số mã từ cuốn sách Lập trình Ruby, nhưng tôi muốn tìm ra cách tốt nhất/đúng và hiểu những gì đang diễn ra. Dưới đây là những gì tôi nhận ban đầu:

exec("whatever --take-very-long") if fork.nil? 
Process.detach($$) 


Vì vậy, đây là đường đi, hoặc làm thế nào khác tôi nên làm điều đó?

Sau khi kiểm tra các câu trả lời dưới đây tôi đã kết thúc với mã này, mà dường như có ý nghĩa hơn:

(pid = fork) ? Process.detach(pid) : exec("foo") 


Tôi đánh giá cao một số giải thích về cách fork công trình. [đã nhận được điều đó]

Đã tách rời $$ phải không? Tôi không biết tại sao nó lại hoạt động, và tôi thực sự thích nắm bắt tình hình tốt hơn.

Trả lời

20

Chức năng fork tách quy trình của bạn thành hai.

Cả hai quá trình đều nhận được kết quả của hàm. Đứa trẻ nhận được một giá trị bằng không/nil (và do đó biết rằng đó là đứa trẻ) và cha mẹ nhận được PID của đứa trẻ.

Do đó:

exec("something") if fork.nil? 

sẽ làm khi bắt đầu tiến trình con "cái gì đó", và quá trình cha mẹ sẽ tiếp tục với nơi nó được.

Lưu ý rằng exec()thay thế quy trình hiện tại bằng "thứ gì đó", vì vậy quy trình con sẽ không bao giờ thực thi bất kỳ mã Ruby tiếp theo nào.

Cuộc gọi tới Process.detach() có vẻ như không chính xác. Tôi đã có thể mong đợi nó có PID của đứa trẻ trong nó, nhưng nếu tôi đọc mã của bạn đúng nó thực sự tách ra quá trình cha mẹ.

+1

Ok, tôi nghĩ mình đã có .nil? kiểm tra. Trong đứa trẻ nó không thực sự trả về 0, nó trả về nil. Vì vậy, exec sẽ chạy nếu bạn đang ở trong đứa trẻ. Vì vậy, sau đó, làm thế nào tôi sẽ nắm bắt được sự trở lại khác của ngã ba, một trong đó trả về id của quá trình con? Bằng cách này tôi có thể sử dụng nó trực tiếp thay vì dựa vào $$. – kch

+2

chỉ cần gọi ngã ba và chụp kết quả. sau đó nếu bạn có nil, làm exec, khác bạn đang ở trong phụ huynh. – Alnitak

+0

Đây là định nghĩa rõ ràng và ngắn gọn về 'ngã ba'. Công việc tuyệt vời, cảm ơn bạn. – KomodoDave

28

Alnitak là đúng. Đây là một cách rõ ràng hơn để viết nó, mà không $$

pid = Process.fork 
if pid.nil? then 
    # In child 
    exec "whatever --take-very-long" 
else 
    # In parent 
    Process.detach(pid) 
end 

Mục đích của cửa sổ mới chỉ là để nói, "Tôi không quan tâm khi trẻ chấm dứt" để tránh zombie processes.

+1

Xin chào, tôi đã chơi với kiến ​​thức mới có được của mình, và về cơ bản tôi đã đến một phiên bản ngắn gọn hơn giống nhau: (pid = fork)? Process.detach (pid): exec ("foo") – kch

+0

Đúng. Điều đó hoạt động. –

+0

@MatthewFlaschen Trong trường hợp này không chứa 'exec', tôi không cần một' exit' trong mã con cho quá trình zombie không kéo dài? – oldergod

2

Tách rời $$ không đúng. Từ P. 348 của Pickaxe (2nd Ed):

$$ Fixnum Số tiến trình của chương trình đang được thực thi.[R/o]

Phần này, "Biến và hằng số" trong chương "Ruby Ngôn ngữ", là rất tiện dụng để giải mã khác nhau ruby ​​ngắn $ hằng - tuy nhiên phiên bản trực tuyến (người đầu tiên

Vì vậy, những gì bạn đang thực sự làm là tách chương trình khỏi chính nó, không phải từ con của nó Giống như những người khác đã nói, cách thích hợp để tách khỏi đứa trẻ là sử dụng pid của đứa trẻ trở về từ fork().

+0

Có điều gì đó borked câu trả lời của bạn. Dù sao tôi có ấn bản thứ ba của cái cuốc. Vì vậy, $$ không đúng, thực tế. Nhưng tại sao nó lại hoạt động? – kch

+2

Nó không hoạt động đúng nếu bạn gọi tách ra trên $$. Nhưng một lần nữa, tách ra chỉ để tránh các quá trình zombie. Nó không phải là cần thiết để thực hiện một công việc chạy trong nền. –

2

Các câu trả lời khác là tốt nếu bạn chắc chắn muốn tách quy trình con. Tuy nhiên, nếu bạn không phiền, hoặc muốn giữ quy trình con được đính kèm (ví dụ: bạn đang tung ra sub-server/dịch vụ cho một ứng dụng web), sau đó bạn có thể tận dụng lợi thế của tốc ký sau

fork do 
    exec('whatever --option-flag') 
end 

Cung cấp một khối nói với ngã ba để thực hiện điều đó khối (và duy nhất khối đó) trong quá trình trẻ em, trong khi tiếp tục trong cha mẹ.

0

tôi đã tìm thấy câu trả lời ở trên đã làm hỏng thiết bị đầu cuối của tôi và làm hỏng đầu ra. đây là giải pháp tôi tìm thấy.

system("nohup ./test.sh &") 

chỉ trong trường hợp bất kỳ ai có cùng vấn đề, mục tiêu của tôi là đăng nhập vào máy chủ ssh và sau đó tiếp tục quá trình đó vô thời hạn. vì vậy test.sh là số này

#!/usr/bin/expect -f 
spawn ssh host -l admin -i cloudkey 
expect "pass" 
send "superpass\r" 
sleep 1000000 
Các vấn đề liên quan