本篇主要介紹PHP實作在linux上執行外部指令的方法,有興趣的朋友參考下,希望對大家有幫助。
目錄:
一、PHP中呼叫外部指令介紹
二、關於安全性問題
三、關於逾時問題
四、關於PHP運行linux環境中命令出現的問題
#一、PHP中呼叫外部命令介紹
在PHP中呼叫外部指令,可以用,1>呼叫專門函數、2>反引號、3>popen()函數開啟進程,三種方法來實作:
#方法一:用PHP提供的專門函數(四個):
PHP提供4個專門的執行外部指令的函數:exec(), system(), passthru(), shell_exec()##1)exec()
原型: string exec (string $command [, array &$output [, int &$return_var ] )說明: exec執行系統外部指令時不會輸出結果,而是傳回結果的最後一行。如果想要得到結果,可以使用第二個參數,讓其輸出到指定的陣列。此數組一個記錄代表輸出的一行。也就是如果輸出結果有20行,則這個陣列就有20筆記錄,所以如果需要重複輸出呼叫不同系統外部指令的結果,最好在輸出每個系統外部指令結果時清空這個陣列unset($output),以防混亂。第三個參數用來取得指令執行的狀態碼,通常執行成功都是回傳0。
<?php exec("dir",$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 signoCan't not find command : 127Can't not execute : 126Shell script successfully executed : return the last command exit status#Fcatat 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"); ?>
說明: 直接執行指令$cmd
<?php $output = shell_exec('ls -lart'); echo "<pre class="brush:php;toolbar:false">$output"; ?>
<?php
echo `dir`;
?>
<?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脚本中将受到如下四个方面的限制:
执行外部命令
在打开文件时有些限制
连接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 "); ?>
但我调用的DOS命令需要几分钟的时间,而且为了批处理不能简单的把结果写入文件了事,要顺序执行以下的程序
PHP设置了调用系统命令的时间限制,如果调用命令超时,虽然这个命令还是会被执行完,但PHP没有得到返回值,被终止了(最可恨的是,不显示任何错误)
修改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上執行外部命令的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!