您好,登錄后才能下訂單哦!
在PHP中執(zhí)行外部程序的方法有哪些?相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
前提
1 PHP沒有運(yùn)行在安全模式,關(guān)掉安全模式,即:safe_mode = off
2 禁用函數(shù)列表 disable_functions = exec, system, shell_exec,proc_open, popen, 如果禁用了,就關(guān)掉。
注意:執(zhí)行外部程序是存在風(fēng)險(xiǎn)的,所以使用這些函數(shù)要在確保安全的情況下使用。
exec() 函數(shù)
原型:string exec ( string command [, array &output [, int &return_var]] )
描述:返回值保存最后的輸出結(jié)果,而所有輸出結(jié)果將會(huì)保存到$output數(shù)組,$return_var用來保存命令執(zhí)行的狀態(tài)碼(用來檢測(cè)成功或失?。?。
例子:
<?php exec('whoami',$output, $status); var_dump($output); exit;
輸出結(jié)果:
array(1) { [0]=> string(7) "hedong" }
注意:
① 輸出結(jié)果會(huì)逐行追加到$output中,因此在調(diào)用exec之前需要unset($output),特別是循環(huán)調(diào)用的時(shí)候。
② 如果想通過exec調(diào)用外部程序后馬上繼續(xù)執(zhí)行后續(xù)代碼,僅僅在命令里加"&"是不夠的,此時(shí)exec依然會(huì)等待命令執(zhí)行完畢;需要再將標(biāo)準(zhǔn)輸出做重定向才可以,例如:exec("ls -al >/dev/null &", $output, $var);
shell_exec() 函數(shù)
原型:string shell_exec( string command)
描述:通過 shell 環(huán)境執(zhí)行命令,并且將完整的輸出以字符串的方式返回。
例子:
<?php $output = shell_exec('whoami'); echo "$output"; // hedong exit;
注意:
當(dāng)進(jìn)程執(zhí)行過程中發(fā)生錯(cuò)誤,或者進(jìn)程不產(chǎn)生輸出的情況下,都會(huì)返回 NULL, 所以,使用本函數(shù)無法通過返回值檢測(cè)進(jìn)程是否成功執(zhí)行。 如果需要檢查進(jìn)程執(zhí)行的退出碼,請(qǐng)使用 exec() 函數(shù)。
system() 函數(shù)
原型:string system ( string command [, int &return_var] )
描述:執(zhí)行給定的命令,返回最后的輸出結(jié)果;第二個(gè)參數(shù)是可選的,用來得到命令執(zhí)行后的狀態(tài)碼。
例子:
<?php system("whoami", $status); // 直接輸出 var_dump($status); // 成功時(shí)狀態(tài)碼是 0 exit;
輸出結(jié)果:hedong
passthru() 函數(shù)
原型:void passthru (string command [, int return_var])
描述:執(zhí)行給定的命令,但不返回任何輸出結(jié)果,而是直接輸出到顯示設(shè)備上;第二個(gè)參數(shù)可選,用來得到命令執(zhí)行后的狀態(tài)碼。
用途:當(dāng)所執(zhí)行的 Unix 命令輸出二進(jìn)制數(shù)據(jù), 并且需要直接傳送到瀏覽器的時(shí)候, 需要用此函數(shù)來替代 exec() 或 system() 函數(shù)
例子:
<?php passthru("whoami", $status); // 直接輸出 var_dump($status); // 成功時(shí)狀態(tài)碼是 0 exit;
輸出結(jié)果:hedong
popen() 函數(shù)
原型:resource popen ( string command, string mode )
描述:打開一個(gè)指向進(jìn)程的管道,該進(jìn)程由派生給定的 command 命令執(zhí)行而產(chǎn)生。 返回一個(gè)和 fopen() 所返回的相同的文件指針,只不過它是單向的(只能用于讀或?qū)懀┎⑶冶仨氂?pclose() 來關(guān)閉。此指針可以用于 fgets(),fgetss() 和 fwrite()。
例子:
$fd = popen("command", 'r'); $ret = fgets($fd);
注意:只能打開單向管道,不是'r'就是'w';并且需要使用pclose()來關(guān)閉。
proc_open() 函數(shù)
原型:resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )
描述:與popen類似,但是可以提供雙向管道。
例子:
<?php /** * @author: hedong * @date 2017-04-04 */ // 管道配置 $descriptors = array( 0 => array("pipe", "r"), 1 => array("pipe", "w") ); $process = proc_open("php", $descriptors, $pipes); if (is_resource($process)) { fwrite($pipes[0], "<?php\n"); fwrite($pipes[0], " \$rand = rand(1,2);\n"); fwrite($pipes[0], " if (\$rand == 1) {\n"); fwrite($pipes[0], " echo \"Hello, World!\n\";\n"); fwrite($pipes[0], " } else {"); fwrite($pipes[0], " echo \"Goodbye, World!\n\";\n"); fwrite($pipes[0], " }"); fwrite($pipes[0], "?>"); fclose($pipes[0]); $output = ""; while (!feof($pipes[1])) { $output .= fgets($pipes[1]); } $output = strtoupper($output); echo $output; fclose($pipes[1]); proc_close($process); }
輸出結(jié)果:
GOODBYE, WORLD!
注意:
① 后面需要使用proc_close()關(guān)閉資源,并且如果是pipe類型,需要用pclose()關(guān)閉句柄。
② proc_open打開的程序作為php的子進(jìn)程,php退出后該子進(jìn)程也會(huì)退出。
總結(jié):
exec函數(shù)將輸出結(jié)果保存在第二個(gè)參數(shù)上;
shell_exec函數(shù)沒有參數(shù)中接收返回值,而且沒有執(zhí)行成功的狀態(tài)碼;
system函數(shù)將執(zhí)行的結(jié)果直接輸出;passthru函數(shù)同system函數(shù),不同之處是適合處理輸出二進(jìn)制數(shù)據(jù);
popen函數(shù)會(huì)fork一個(gè)子進(jìn)程,返回文件指針
proc_open函數(shù)同popen,但可提供雙向通道
看完上述內(nèi)容,你們掌握在PHP中執(zhí)行外部程序的方法有哪些的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。