2010-01-25 70 views

回答

17

perlfaq8的答案How do I start a process in the background?


幾個模塊可以啓動不會阻止你的Perl 程序等工序。您可以使用IPC :: Open3,Parallel :: Jobs,IPC :: Run和POE模塊中的一些 。有關更多詳情,請參閱CPAN。

你也可以使用

system("cmd &") 

或在perlfunc記錄在「叉」,在perlipc進一步 例子,你可以使用叉子。有些事情需要注意,如果你使用的是Unix的 像系統:

STDIN,STDOUT和STDERR是共享的

兩個主要過程和背景執行一個(「子」 進程)共享相同的STDIN,STDOUT和STDERR文件句柄。如果 都試圖一次訪問它們,可能會發生奇怪的事情。您可能想要爲孩子關閉或重新打開這些內容。你可以通過打開一個管道(見perlfunc中的「open」)在 附近得到 ,但在 的某些系統上,這意味着子進程不能超過父進程 。

信號

你必須趕上SIGCHLD信號,可能還有SIGPIPE了。 當後退過程結束時發送SIGCHLD。當您寫入子進程已關閉的文件句柄 (未處理的SIGPIPE可能會導致程序靜默死亡)時,發送SIGPIPE爲 。 這不是「系統(」cmd &「)」的問題。

殭屍

你必須做好準備,「收穫」,當它完成 子進程。

$SIG{CHLD} = sub { wait }; 

    $SIG{CHLD} = 'IGNORE'; 

您還可以使用雙叉。您立即等待()您的 第一個孩子,並且init守護進程將等待()爲您的孫子 一旦退出。

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

請參閱perlipc中的「信號」以獲取其他代碼示例。 「系統(」編&「)」並不是「殭屍」的問題。

+0

非常感謝,我沒有想過在命令中使用後臺shell操作符。那就是訣竅。不幸的是,我不能使用其他人,因爲我正在使用幾乎沒有模塊的嚴格限制系統。 – 2010-01-25 20:23:57

+0

啊,沒錯,如果你用'&'char命令發出system()命令,它會立即返回,因此我建議的反標操作符方法並不好 - 最好使用Perl的系統調用而不是調用整個shell的新副本。 – 2010-01-25 23:28:50

1

如果你想守護進程的Perl腳本我已經尋找到Proc::Daemon.

+0

實際上,我不想守護它,我只需要在執行我的主腳本的時候在後臺啓動一個監視腳本。而且我只能使用基本的Perl 5.6.0,因爲這是在內存嚴重有限的嵌入式系統上執行的,我幾乎沒有任何模塊可以使用。 – 2010-01-25 16:57:31

0

那麼你不應該使用system()我瞭解這個呼叫等待功能的繼續執行之前的回報。我只是簡單地向linux發送消息,並以這種方式啓動進程,但請記住,這種方式將啓用shell的新副本,因此如果您正在尋找性能,我不會在循環中執行此操作,例如:

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

這將啓動過程重定向STDOUTSTDERR/dev/null

0

如果您希望在「父」進程退出時看門狗「子」進程消失,那麼您並不希望父進程「觸發並忘記」該子進程。您可能需要fork(如brian d foy所述)或將父項的PID傳遞給子項(所以後者可以輪詢流程表 - 不推薦)。

+0

實際上,運行一個看門狗腳本作爲一個子進程可能是一個壞主意,因爲如果主腳本意外死掉(但是如果父母死了,那麼所有的孩子都這麼做),大概是看守應該做些什麼。 另一種方法是讓「主進程」設置一個命名管道,並在退出時寫入「心跳」消息+「完成」消息,而看門狗(以真正的「fire and forget」模式啓動系統(「cmd&」))從命名管道讀取,並在「完成」消息到達或「心跳」消息停止時發出通知。 – Peter 2010-01-25 22:34:43

相關問題