19.4 使用程序执行函数

现在,我们要将视线从文件系统函数转移到能够运行服务器命令的函数。

当要为一个已有的命令行系统提供一个基于Web的前台时,这些函数是非常有用的。例如,我们使用这些命令为邮件清单管理器ezmlm建立了一个前台。当我们在本书后面的部分讨论实例时,将再次使用这些函数。

可以使用4种主要的技术在Web服务器上执行命令。这些技术都非常相似,但也有一些微小的区别:

■exec()——exec()函数原型如下所示:


string exec(string command[,array&result[,int&return_value]])


可以将要执行的命令作为输入参数传递给该函数,例如:


exec("ls-la");


该函数exec()没有直接的输出。此函数将返回命令结果的最后一行。

如果以result传递一个变量,此函数将返回字符串组数,这些字符串代表输出的每一行。

如果以return_value传递一个变量,将获得返回代码。

■passthru()——函数passthru()原型如下所示:


void passthru(string command[,int return_value])


函数passthru()直接将输出显示到浏览器。(如果输出是二进制,例如一些图像数据,这是非常有用的。)此函数无返回值。

此函数的参数与函数exec()的参数格式一样。

■system()——函数system()原型如下:


string system(string command[,int return_value])


此函数将该命令的输出回显到浏览器。它将把每一行的输出向后对齐(假设以服务器模块运行PHP),这就是与passthru()函数的不同之处。此函数返回输出(如果成功运行)的最后一行或false(如果失败)。

函数的参数与其他函数的参数格式一样。

■反引号——我们在第1章中简单地提到过它。这些实际上是可执行的操作符。它们没有直接的输出。执行这个命令的结果是以字符串的形式返回的,我们可以决定是否显示这些字符串。

如果有更复杂的需求,也可以使用popen()、proc_open()和proc_close()函数,这些函数可以启动外部进程,并且在这些进程之间传递数据。其中,后两个函数是在PHP 4.3版本中新添加的。

程序清单19-7所示的脚本说明如何使用这些函数来实现相同的功能。

程序清单19-7 progex.php——文件状态函数和它们的输出结果


<?php

chdir('/uploads/');

/////exec version

echo'<pre>';

//unix

exec('ls-la',$result);

//windows

//exec('dir',$result);

foreach($result as$line)

echo"$line\n";

echo'</pre>';

echo'<br><hr><br>';

/////passthru version

echo'<pre>';

//unix

passthru('ls-la');

//windows

//passthru('dir');

echo'</pre>';

echo'<br><hr><br>';

/////system version

echo'<pre>';

//unix

$result=system('ls-la');

//windows

//$result=system('dir');

echo'</pre>';

echo'<br><hr><br>';

/////backticks version

echo'<pre>';

//unix

$result=ls-al;

//windows0

//$result=dir;

echo$result;

echo'</pre>';

?>


我们可以使用以上方法中的任何一种方法来替代前面所介绍的目录浏览脚本。请注意,以上代码充分说明了使用外部函数的一个缺点——代码不再是可移植的。在这里,我们使用了UNIX命令,因此,这些代码将肯定无法在Windows上运行。

如果打算把用户提交的数据包括在将执行命令的一部分,首先应该通过函数escapeshellcmd()来运行它。此函数将阻止用户在系统上恶意地执行命令。可以按如下方式来调用这个函数:


system(escapeshellcmd($command));


也应该使用escapeshellarg()函数来整理任何要传递给shell命令的参数。