2010-01-25 22 views

Trả lời

17

Từ câu trả lời perlfaq8 's để How do I start a process in the background?


Một số module có thể bắt đầu quá trình khác mà không chặn chương trình Perl của bạn. Bạn có thể sử dụng IPC :: Open3, Parallel :: Jobs, IPC :: Run và một số mô-đun POE . Xem CPAN để biết thêm chi tiết.

Bạn cũng có thể sử dụng

system("cmd &") 

hoặc bạn có thể sử dụng nĩa như tài liệu trong "ngã ba" trong perlfunc, với thêm ví dụ trong perlipc. Một số điều cần phải nhận thức được, nếu bạn đang ở trên một Unix- như hệ thống:

STDIN, STDOUT, và stderr được chia sẻ

Cả hai quá trình chính và một background (những "đứa trẻ" quy trình) chia sẻ cùng một tệp STDIN, STDOUT và STDERR. Nếu cả hai cố gắng truy cập chúng cùng một lúc, những điều kỳ lạ có thể xảy ra. Bạn có thể muốn đóng hoặc mở lại chúng cho trẻ. Bạn có thể nhận được xung quanh điều này với "mở" ing một đường ống (xem "mở" trong perlfunc) nhưng trên một số hệ thống này có nghĩa là quá trình con không thể sống lâu hơn phụ huynh .

Tín hiệu

Bạn sẽ phải nắm bắt những tín hiệu SIGCHLD, và có thể SIGPIPE quá. SIGCHLD được gửi khi quá trình nền kết thúc. SIGPIPE là được gửi khi bạn viết thư cho người nộp hồ sơ có quá trình con đã đóng (một SIGPIPE chưa được khai báo có thể khiến chương trình của bạn âm thầm chết). Đây không phải là vấn đề với "hệ thống (" cmd & ")".

Zombies

Bạn cần phải được chuẩn bị để "gặt hái" quá trình đứa trẻ khi nó kết thúc.

$SIG{CHLD} = sub { wait }; 

    $SIG{CHLD} = 'IGNORE'; 

Bạn cũng có thể sử dụng một ngã ba đôi. Bạn ngay lập tức chờ đợi() cho con đầu tiên của bạn và daemon init sẽ đợi() cho cháu của bạn khi nó thoát.

unless ($pid = fork) { 
     unless (fork) { 
      exec "what you really wanna do"; 
      die "exec failed!"; 
     } 
     exit 0; 
    } 
    waitpid($pid, 0); 

Xem "Tín hiệu" trong perlipc để biết các ví dụ mã khác để thực hiện việc này. Zombies không phải là vấn đề với "hệ thống (" prog & ")".

+0

Cảm ơn bạn rất nhiều, tôi đã không nghĩ đến việc sử dụng toán tử vỏ nền trong lệnh. Điều đó đã làm các trick. Thật không may tôi không thể sử dụng những người khác bởi vì tôi đang làm việc trên một hệ thống bị hạn chế nghiêm trọng với hầu như không có mô-đun. –

+0

Đúng vậy, nếu bạn đưa ra lệnh system() với '&' char nó trả về ngay lập tức, do đó phương thức toán tử back-tick mà tôi đã đề xuất không tốt lắm - tốt hơn để sử dụng cuộc gọi hệ thống của Perl thay vì gọi toàn bộ bản sao mới của trình bao. –

1

Nếu bạn muốn daemonize kịch bản Perl của bạn tôi đã nhìn vào Proc::Daemon.

+0

Thực ra, tôi không muốn sao chép nó, tôi chỉ cần khởi chạy tập lệnh cơ quan giám sát trong nền trong suốt thời gian thực thi tập lệnh chính của tôi. Và tôi chỉ có Perl 5.6.0 cơ bản để làm việc với, vì điều này đang thực thi trên một hệ thống nhúng với bộ nhớ bị hạn chế nghiêm trọng và tôi không có nhiều mô-đun để làm việc. –

0

Vâng, bạn không nên sử dụng system() như tôi hiểu cuộc gọi này sẽ chờ đợi sự trở lại của các chức năng trước khi tiếp tục thực hiện. Tôi chỉ đơn giản là shell ra Linux và bắt đầu quá trình như vậy, mặc dù hãy ghi nhớ theo cách này sẽ envoke một bản sao mới của vỏ và vì vậy nếu bạn đang tìm kiếm hiệu suất tôi sẽ không làm điều này trong một vòng lặp ví dụ:

process_name > /dev/null 2>&1 &;

Điều đó sẽ bắt đầu quá trình chuyển hướng STDOUTSTDERR đến /dev/null.

0

Nếu bạn muốn quá trình "con" giám sát bị biến mất khi quá trình "cha mẹ" thoát ra thì bạn không thực sự muốn quy trình cha mẹ "kích hoạt và quên" quá trình con. Bạn cần phải ngã ba (như được mô tả bởi brian d foy) hoặc chuyển PID của cha mẹ cho đứa trẻ (vì vậy sau này có thể thăm dò ý kiến ​​của bảng tiến trình - không được khuyến nghị).

+0

Trên thực tế, chạy kịch bản watchdog như là một quá trình con có lẽ là một ý tưởng tồi vì có lẽ cơ quan giám sát phải làm gì đó nếu kịch bản chính chết bất ngờ (nhưng nếu cha mẹ chết thì hãy làm tất cả các con của nó). Một cách khác để đi là có "quy trình chính" thiết lập một đường ống có tên và viết "nhịp tim" tin nhắn cho nó + thông báo "đã hoàn tất" khi thoát, trong khi cơ quan giám sát (khởi chạy ở chế độ "lửa và quên" thực sự qua system ("cmd &")) đọc từ các đường ống có tên và các thông báo khi một thông báo "đã hoàn thành" đến hoặc các thông báo "heartbeat" dừng lại. – Peter

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