天天看點

php執行外部指令linux指令方式介紹

一、PHP中調用外部指令介紹

二、關于安全問題

三、關于逾時問題

四、關于PHP運作linux環境中指令出現的問題

一、PHP中調用外部指令介紹

在PHP中調用外部指令,可以用,1>調用專門函數、2>反引号、3>popen()函數打開程序,三種方法來實作:

方法一:用PHP提供的專門函數(四個):

PHP提供4個專門的執行外部指令的函數:exec(), system(), passthru(), shell_exec()

注意事項:

由于PHP配置中的php.ini預設設定了禁用了執行系統外部指令函數:exec()、passthru()、system()、shell_exec(),

因為PHP預設php.ini配置檔案中是不允許你調用執行外部指令的函數的。執行時會出現錯誤提示

has been disabled for security

找到PHP配置檔案php.ini 将 “disable_functions=”後面有接上面四個函數删除,就可以了

1)exec()

原型: string exec ( string $command [, array &$output [, int &$return_var ] )

說明: exec執行系統外部指令時不會輸出結果,而是傳回結果的最後一行。如果想得到結果,可以使用第二個參數,讓其輸出到指定的數組。此數組一個記錄代表輸出的一行。即如果輸出結果有20行,則這個數組就有20條記錄,是以如果需要反複輸出調用不同系統外部指令的結果,最好在輸出每一條系統外部指令結果時清空這個數組unset($output),以防混亂。第三個參數用來取得指令執行的狀态碼,通常執行成功都是傳回0。

<?php
  exec("ls ./",$output);
  print_r($output);
?>
           

2)system()

原型: string system ( string $command [, int &$return_var ] )

說明: system和exec的差別在于,system在執行系統外部指令時,它執行給定的指令,輸出和傳回結果。第二個參數是可選的,用來得到指令執行後的狀态碼。

<?php
system("pwd",$result);
print $result;//輸出指令的結果狀态碼
?>
           

關于第二個參數結果狀态碼的簡單介紹:

如果傳回0是運作成功,

在Bash中,當錯誤發生在緻命信号時,bash會傳回128+signal number做為傳回值。

如果找不到指令,将會傳回127。

如果指令找到了,但該指令是不可執行的,将傳回126。

除此以外,Bash本身會傳回最後一個指令的傳回值。

若是執行中發生錯誤,将會傳回一個非零的值。

Fatal Signal : 128 + signo

Can't not find command : 127

Can't not execute : 126

Shell script successfully executed : return the last command exit status

Fatal during execution : return non-zero

3)passthru()

原型: void passthru ( string $command [, int &$return_var ] )

說明: passthru與system的差別,passthru直接将結果輸出到遊覽器,不傳回任何值,且其可以輸出二進制,比如圖像資料。第二個參數可選,是狀态碼。

<?php
header("Content-type:image/gif");
passthru("/usr/bin/ppm2tiff /usr/share/tk8.4/demos/images/teapot.ppm");
?>
           

4)shell_exec()

原型: string shell_exec ( string $cmd )

說明: 直接執行指令$cmd

<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>
           

方法二:反撇号

原型: 反撇号`(和~在同一個鍵)執行系統外部指令

說明: 在使用這種方法執行系統外部指令時,要確定shell_exec函數可用,否則是無法使用這種反撇号執行系統外部指令的。

<?php
  echo `dir`;
?>
           

方法三:用popen()函數打開程序

原型: resource popen ( string $command , string $mode )

說明: 能夠和指令進行互動。之前介紹的方法隻能簡單地執行指令,卻不能與指令互動。有時須向指令輸入一些東西,如在增加系統使用者時,要調用su來把目前使用者換到root使用者,而su指令必須要在指令行上輸入root的密碼。這種情況下,用之前提到的方法顯然是不行的。

popen( )函數打開一個程序管道來執行給定的指令,傳回一個檔案句柄,可以對它讀和寫。傳回值和fopen()函數一樣,傳回一個檔案指針。除非使用的是單一的模式打開(讀or寫),否則必須使用pclose()函數關閉。該指針可以被fgets(),fgetss(),fwrite()調用。出錯時,傳回FALSE。

<?php
error_reporting(E_ALL);
  
/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>
           

二、關于安全問題:

由于PHP基本是用于WEB程式開發的,是以安全性成了人們考慮的一個重要方面。

于是PHP的設計者們給PHP加了一個門:安全模式。

在php.ini中的設定safe_mode = On

如果運作在安全模式下,那麼PHP腳本中将受到如下四個方面的限制:

執行外部指令

在打開檔案時有些限制

連接配接MySQL資料庫

基于HTTP的認證

在安全模式下,隻有在特定目錄中的外部程式才可以被執行,對其它程式的調用将被拒絕。這個目錄可以在php.ini檔案中用safe_mode_exec_dir指令,或在編譯PHP 是加上–with-exec-dir選項來指定,預設是/usr/local/php/bin。

當你使用這些函數來執行系統指令時,可以使用escapeshellcmd()和escapeshellarg()函數阻止使用者惡意在系統上執行指令,escapeshellcmd()針對的是執行的系統指令,而escapeshellarg()針對的是執行系統指令的參數。這兩個參數有點類似addslashes()的功能。

三、關于逾時問題

當執行指令的傳回結果非常龐大時,可以需要考慮将傳回結果輸出至其他檔案,再另行讀取檔案,這樣可以顯著提高程式執行的效率。

如果要執行的指令要花費很長的時間,那麼應該把這個指令放到系統的背景去運作。但在預設情況下,象system()等函數要等到這個指令運作完才傳回(實際上是在等指令的輸出結果),這肯定會引起PHP腳本的逾時。解決的辦法是把指令的輸出重定向到另外一個檔案或流中,如:

<?php

system("/usr/local/bin/order_proc > /tmp/abc ");

?>
           

PHP設定了調用系統指令的時間限制,如果調用指令逾時,雖然這個指令還是會被執行完,但PHP沒有得到傳回值,被終止了(最可恨的是,不顯示任何錯誤)但我調用的DOS指令需要幾分鐘的時間,而且為了批處理不能簡單的把結果寫入檔案了事,要順序執行以下的程式

修改php.ini并重新開機Apache以允許系統指令運作更長的時間

max_execution_time = 600

四、關于PHP運作linux環境中指令出現的問題

php一般是以apache使用者身份去執行的,也可能是www使用者,把apache加入到存儲你檔案的父檔案夾屬組裡去,然後改該父檔案夾權限為775,這樣屬組成員就有寫的權限,而apache屬于這個組就可以改寫該目錄下所有檔案的權限。

例如:chown www:www dirName

這樣dirName目錄才能被php所控制

注意:改apache/php的運作使用者方法不安全

另外即使檔案或目錄已經是www,php的安全設定也都照顧到,一些自己安裝linux的指令仍然可能無法運作,例如我曾經安裝的ffmpeg軟體,原因就是linux的運作權限問題,即使ffmpeg有www權限設定,但由于ffmpeg所依賴的庫檔案是不允許www使用者運作,是以php運作此程式仍然會報127或126錯誤,通過 ldd 指令可以檢視ffmpeg指令依賴的庫情況。

這個時候就必須對ffmpeg的依賴庫經行設定。具體方法屬于linux管理中的話題,這裡不就讨論了。

以上這篇PHP在linux上執行外部指令的方法就是小編分享給大家的全部内容了,希望能給大家一個參考,也希望大家多多支援腳本之家。