[原文地址:https://blog.ti-node.com/blog…]
daemon 音標 : [`di:mən] , 中文含義為守護神或精靈的意思 . 其實它還有個意思 : 守護程式 .
守護程式簡單地說就是可以脫離終端而在後臺執行的程式 . 這在Linux中是非常常見的一種程式 , 比如apache或者mysql等服務啟動後 , 就會以守護程式的方式進駐在記憶體中 .
以PHP為例 , 假如我有個耗時間的任務需要跑在後臺 : 將所有mysql中user表中的2000萬使用者全部匯入到redis中做預熱快取 , 那麼這個任務估計一時半會是不會結束的 , 這個時候就需要編寫一個php指令碼以daemon形式執行在系統中 , 結束後自動推出 .
在Linux中 , 大概有三種方式實現指令碼後臺化 :
1 . 在命令後新增一個&符號 , 比如 php task.php & . 這個方法的缺點在於 如果terminal終端關閉 , 無論是正常關閉還是非正常關閉 , 這個php程式都會隨著終端關閉而關閉 , 其次是程式碼中如果有echo或者print_r之類的輸出文字 , 會被輸出到當前的終端視窗中 .
2 . 使用nohup命令 , 比如 nohup php task.php & . 預設情況下 , 程式碼中echo或者print_r之類輸出的文字會被輸出到php程式碼同級目錄的nohup.out檔案中 . 如果你用exit命令或者關閉按鈕等正常手段關閉終端 , 該程式不會被關閉 , 依然會在後臺持續執行 . 但是如果終端遇到異常退出或者終止 , 該php程式也會隨即退出 . 本質上 , 也並非穩定可靠的daemon方案 .
3 . 使用fork和setsid , 我暫且稱之為 : *nix解決方案 . 具體看下程式碼 :
<?php
// 一次fork
$pid = pcntl_fork();
if ( $pid < 0 ) {
exit( ` fork error. ` );
} else if( $pid > 0 ) {
exit( ` parent process. ` );
}
// 將當前子程式提升會會話組組長 這是至關重要的一步
if ( ! posix_setsid() ) {
exit( ` setsid error. ` );
}
// 二次fork
$pid = pcntl_fork();
if( $pid < 0 ){
exit( ` fork error. ` );
} else if( $pid > 0 ) {
exit( ` parent process. ` );
}
// 真正的邏輯程式碼們 下面僅僅寫個迴圈以示例
for( $i = 1 ; $i <= 100 ; $i++ ){
sleep( 1 );
file_put_contents( `daemon.log`, $i, FILE_APPEND );
}
?>