PHP exec退出問題是在使用exec函數(shù)執(zhí)行命令時,出現(xiàn)了不能有效退出的情況,進而導致程序出現(xiàn)blocked的問題。例如:
$command = "ping -c 10 www.baidu.com"; exec($command); echo "Exec done!";
以上代碼執(zhí)行時會被阻塞,程序無法繼續(xù)正常執(zhí)行。這是因為exec函數(shù)默認情況下是等待被調(diào)用進程執(zhí)行完畢后才會返回,否則會被阻塞。
為了解決該問題,可以使用以下辦法:
1.在命令行中添加后臺執(zhí)行符號&,讓進程在后臺執(zhí)行
$command = "ping -c 10 www.baidu.com &"; exec($command); echo "Exec done!";
加上&符號后,command命令執(zhí)行后,系統(tǒng)立即返回,不會等待command執(zhí)行完畢了,進而不會阻塞PHP執(zhí)行。
2.在命令末尾加上無輸出的操作
$command = "ping -c 10 www.baidu.com >/dev/null &"; exec($command); echo "Exec done!";
加上>/dev/null則將輸出重定向到了空設備,進程的輸出則被丟棄了。進程不會被console阻塞,PHP執(zhí)行也不會受到阻塞。
但值得注意的是,在以上兩種情況下,如果PHP代碼執(zhí)行過程中執(zhí)行的命令中含有read操作,則執(zhí)行結果是不完整的。這是因為存在無法停止的read操作會阻塞整個進程。
因此,若要實現(xiàn)完整處理命令的執(zhí)行和輸出,應該使用syste函數(shù)或者proc_open函數(shù),如:
passthru('ping -c 10 www.baidu.com'); echo "Done";
或者
$descriptorspec = array( 0 =>array("pipe", "r"), // 標準輸入,子進程通過此pipe讀取數(shù)據(jù) 1 =>array("pipe", "w"), // 標準輸出,子進程通過此pipe輸出數(shù)據(jù) 2 =>array("pipe", "w") // 標準錯誤,子進程通過此pipe輸出數(shù)據(jù) ); $process = proc_open("ping -c 10 www.baidu.com", $descriptorspec, $pipes); if (is_resource($process)) { fwrite($pipes[0], 'STDIN'); fclose($pipes[0]); echo stream_get_contents($pipes[1]); fclose($pipes[1]); $error = stream_get_contents($pipes[2]); fclose($pipes[2]); $returnValue = proc_close($process); echo $returnValue; echo "Done"; }
這兩種情況下,執(zhí)行效果更加完整。