php執(zhí)行shell時,如何異步調(diào)用使得不會超時?
網(wǎng)友解答: 首先,超時和在后臺運行是兩碼事PHP超時設(shè)置php配置中默認(rèn)有個超時設(shè)置,默認(rèn)好像是30秒超時,如果確實是程序超時問題,你需要修改下設(shè)置,或者在你腳本中設(shè)下超時參數(shù)。1、ph
首先,超時和在后臺運行是兩碼事
PHP超時設(shè)置php配置中默認(rèn)有個超時設(shè)置,默認(rèn)好像是30秒超時,如果確實是程序超時問題,你需要修改下設(shè)置,或者在你腳本中設(shè)下超時參數(shù)。
1、php.ini中超時設(shè)置2、代碼中設(shè)置超時ini_set("max_execution_time",30);
set_time_limit(30);
比如我么舉個小例子:
注意這兩個設(shè)置只對運行程序的這個這個連接回話生效,設(shè)置為了0是用不超時間。php.ini 如果設(shè)置safe_mode模式,腳本中的設(shè)置不成立。
效果一樣,但是具體內(nèi)容需要參考php-fpm部分內(nèi)容,如果php-fpm中設(shè)置了request_terminate_timeout的話,那么max_execution_time就不生效。
PHP程序后臺運行一般如果運行量很大,需要大量時間執(zhí)行的程序,需要調(diào)用第三方程序或者作為網(wǎng)路客戶端的程序,不建議直接用php跑,可以用shell、perl、python等腳本替代。
程序調(diào)用時候,建議用如下方式:
exec(sprintf("%s %s 2&1 & echo $! %s", $cmd, $outputfile, $pidfile));
這個會執(zhí)行$cmd變量報錯的命令,并把輸出結(jié)果(包括錯誤信息)都重定向到$outputfile指定的輸出文件。執(zhí)行的進程號輸入到$pidfile指定的文件。這樣執(zhí)行的好處是你可以隨時得到你程序執(zhí)行的輸出,根據(jù)pid文件中的進程號你也可隨時通過ps命令查看執(zhí)行進程是否還在運行,執(zhí)行的情況如何。
但是這樣也有個問題,雖然你的執(zhí)行進程是后臺執(zhí)行的,但是你php如果是你手動在shell下執(zhí)行的話,你退出shell或者直接關(guān)閉了shell窗口你php主程序也會完蛋,會導(dǎo)致你其他php部分運行完全中斷。所以我們介紹其他方法保持你php腳本在后臺執(zhí)行的:
1、cron進程任務(wù)把你的php腳本加入到cron中,這樣他可以定時執(zhí)行,不用人為干擾,后臺執(zhí)行。這種方法網(wǎng)上介紹很多,不多做介紹。
2、寫一個前臺腳本,一個后臺腳本弄兩個腳本一個前臺腳本,一個后臺腳本前臺腳本啟動后臺腳本,舉個例子(這是gnu win32包里面的例子)
后臺腳本(test-proc-bg.php):
sleep(5);
file_put_contents('test.txt', date('Y-m-d/H:i:s.u'));
我們前臺用wget.ext
$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);
我們注意下wget的參數(shù),說明如下:
-q 靜默模式
-O - 輸出到標(biāo)準(zhǔn)輸出
-b 后臺運行
前臺也可以用screen啟動后臺
shell_exec('screen -dmS $name $cmd');
$cmd為執(zhí)行的命令 -S $name表示回話的名稱,之后可以用screen -r $name 進入那個screen執(zhí)行窗口(確保你機器已經(jīng)安裝過screen,默認(rèn)下linux都是會安裝的)。
php后臺執(zhí)行啟動器最后我們奉上一個后臺執(zhí)行的啟動器(前臺執(zhí)行函數(shù)):
function LaunchBackgroundProcess($command){
if(PHP_OS=='WINNT' || PHP_OS=='WIN32' || PHP_OS=='Windows'){
// Windows下
$command = 'start "" '. $command;
} else {
// Linux/UNIX下
$command = $command .' /dev/null &';
}
$handle = popen($command, 'r');
if($handle!==false){
pclose($handle);
return true;
} else {
return false;
}
}