PHP 执行外部命令函数:exec()、system()、passthru()、shell_exec()、popen()
PHP内置函数,提供了4种方法执行系统外部命令:
exec()、system()、passthru()、 shell_exec()
查看命令函数配置
在开始介绍前,先检查下php配置文件php.ini中是有禁止这是个函数
vim /etc/php.ini 或 vim /usr/local/php/lib/php.ini
php.ini 默认配置文件中是不禁止你调用执行外部命令的函数的。
找到 disable_functions,正常开启的配置为 disable_functions = ,具体如下:
; This directive allows you to disable certain functions for security reasons. ; It receives a comma-delimited list of function names. This directive is ; *NOT* affected by whether Safe Mode is turned On or Off. ; http://php.net/disable-functions disable_functions =
如果“disable_functions=”后面有接上面四个函数,将其删除,并重启 httpd 或 php-fpm
原型:string exec ( string $command
[, array &$output
[, int &$return_var
]] )
说明:
第一个参数, $command 是要执行的命令,例如: "ls -l"
第二个参数,$output 是command执行输出的结果,以数组格式存储
第三个参数,$return_var,用于保存command执行状态,0 - 成功,非零 - 失败
返回值,为command执行结果的最后一行
示例:
// exec $retval = null; $res = null; $res_array = array(); $cmd = "/usr/bin/curl -k --head 'https://mimvp.com'"; $res = exec($cmd, $res_array, $retval); echo "<br><br> exec result:"; var_dump($retval); // 0 (返回的状态, 0 - 成功, 非零 - 失败) var_dump($res); // '' var_dump($res_array); // 返回结果数组
运行结果:
exec result: /Users/homer/mimvp_site/api/header2.php:55:int 0 /Users/homer/mimvp_site/api/header2.php:56:string '' (length=0) /Users/homer/mimvp_site/api/header2.php:57: array (size=9) 0 => string 'HTTP/2 200' (length=10) 1 => string 'server: nginx' (length=13) 2 => string 'date: Tue, 26 Dec 2017 01:52:11 GMT' (length=35) 3 => string 'content-type: text/html; charset=UTF-8' (length=38) 4 => string 'vary: Accept-Encoding' (length=21) 5 => string 'vary: Accept-Encoding' (length=21) 6 => string 'vary: mimvp-home-bj2' (length=20) 7 => string 'vary: mimvp-homes-bj2' (length=21) 8 => string '' (length=0)
从结果看
1)第二行结果 $retval 为状态 0 ,表示 cmd 命令执行成功
2)第三行结果 $res 为空字符串 '',表示 cmd 命令执行返回结果的最后一行,见 $res_array 数组最后一行(第八行)为空
3)第五行结果 $res_array 保存了完整的 cmd 命令执行结果,说明第二个参数保存 exec 执行结果
知识点:
exec 执行系统外部命令时,只返回结果的最后一行,如果想得到完整的执行结果,需要使用第二个参数,让其输出到指定的数组,此数组一个记录代表输出的一行,即如果输出结果有20行,则这个数组就有20条记录。所以,如果你需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组 $res_array = array(),以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0
原型:string system ( string $command
[, int &$return_var
] )
说明:
第一个参数, $command 是要执行的命令,例如: "ls -l"
第二个参数,$return_var,用于保存command执行状态,0 - 成功,非零 - 失败
返回值,为command执行结果的最后一行(system 和 exec 类似),失败返回 FALSE
示例:
// system $retval = null; $res = null; $cmd = "/usr/bin/curl -k --head 'https://mimvp.com'"; $res = system($cmd, $retval); echo "<br><br> system result:"; var_dump($retval); // 0 (返回的状态, 0 - 成功, 非零 - 失败) var_dump($res); // ''
运行结果:
cmd : /usr/bin/curl -k --head 'https://mimvp.com'HTTP/2 200 server: nginx date: Tue, 26 Dec 2017 01:52:11 GMT content-type: text/html; charset=UTF-8 vary: Accept-Encoding vary: Accept-Encoding vary: mimvp-home-bj2 vary: mimvp-homes-bj2 system result: /Users/homer/mimvp_site/api/header2.php:41:int 0 /Users/homer/mimvp_site/api/header2.php:42:string '' (length=0)
从结果看
1)第一行结果,打印输出命令时,直接在屏幕上打印了 sytem 执行命令的返回结果,没法保存,因此system用于不保存结果的场景
2)第三行结果 $retval 为状态 0 ,表示 cmd 命令执行成功
3)第四行结果 $res 为空字符串 '',表示 cmd 命令执行返回结果的最后一行,其结果为空
原型:void passthru ( string $command
[, int &$return_var
] )
passthru 和 system 基本是一样的,结果不保存,直接输出在屏幕上,两者仅是返回值不同
1)system 是返回结果的最后一行,类型为 string
2)passthru 不返回结果,类型为 void
说明:
第一个参数, $command 是要执行的命令,例如: "ls -l"
第二个参数,$return_var,用于保存command执行状态,0 - 成功,非零 - 失败
返回值,为空 void
示例:
// passthru $retval = null; $res = null; $cmd = "/usr/bin/curl -k --head 'https://mimvp.com'"; $res = passthru($cmd, $retval); echo "<br><br> passthru result:"; var_dump($retval); // 0 (返回的状态, 0 - 成功, 非零 - 失败) var_dump($res); // ''
运行结果:
HTTP/2 200 server: nginx date: Tue, 26 Dec 2017 01:52:11 GMT content-type: text/html; charset=UTF-8 vary: Accept-Encoding vary: Accept-Encoding vary: mimvp-home-bj2 vary: mimvp-homes-bj2 passthru result: /Users/homer/mimvp_site/api/header2.php:48:int 0 /Users/homer/mimvp_site/api/header2.php:49:null
从结果看
1)第一行结果,打印输出命令时,直接在屏幕上打印了 sytem 执行命令的返回结果,没法保存,跟system类似
2)第三行结果 $retval 为状态 0 ,表示 cmd 命令执行成功
3)第四行结果 $res 为空字符串为null,即不返回结果 void
原型:string shell_exec ( string $cmd
)
shell_exec 与 exec 类似,只是没有返回状态,其状态和cmd执行结果,都以结果返回
1)如果执行cmd成功,则返回执行结果
2)如果执行cmd失败,则返回 NULL
说明:
第一个参数, $command 是要执行的命令,例如: "ls -l"
返回值,为command执行结果,如果失败则返回 NULL
示例:
// shell_exec $res = null; $cmd = "/usr/bin/curl -k --head 'https://mimvp.com'"; $res = shell_exec($cmd); echo "<br><br> shell_exec result:"; var_dump($res); // 返回执行结果,或失败返回NULL
运行结果:
shell_exec result: /Users/homer/mimvp_site/api/header2.php:84:string 'HTTP/2 200 server: nginx date: Tue, 26 Dec 2017 01:52:11 GMT content-type: text/html; charset=UTF-8 vary: Accept-Encoding vary: Accept-Encoding vary: mimvp-home-bj2 vary: mimvp-homes-bj2 ' (length=198)
从结果看
执行cmd输出结果,以字符串返回给了 $res ,并保留了换行
原型:resource popen ( string $command
, string $mode
)
通过pipe管道执行shell命令,也是一种常见的方式,python也有类似的命令
说明:
第一个参数, $command 是要执行的命令,例如: "ls -l"
第二个参数,$mode 是指定读写、执行等操作类型,如 'r', 'w', 'x'
返回值,是一个资源句柄,可用来具体的操作命令的资源,一般配合 fgets()、fgetss()、fwrite() 使用
示例:
// popen $handle = popen($cmd, 'r'); $res = fread($handle, 8888); echo "<br><br> popen result:"; var_dump($res); pclose($handle); // 资源句柄执行完后,一定要记得关闭
运行结果:
popen result: /Users/homer/mimvp_site/api/header2.php:90:string 'HTTP/2 200 server: nginx date: Tue, 26 Dec 2017 02:57:55 GMT content-type: text/html; charset=UTF-8 vary: Accept-Encoding vary: Accept-Encoding vary: mimvp-home-bj2 vary: mimvp-homes-bj2 ' (length=198)
PHP 执行命令函数的应用实例
PHP 执行外部命令函数 exec()、system()、passthru()、shell_exec() 不是花瓶,一切皆因需求而生
例如,PHP 前端执行直接从shell获取一些查询结果,充分利用强大的shell命令,如 curl、wget、whois 等
PHP 内置函数 get_headers() 用于获取服务器端返回的头信息,如果失败了可以通过 curl --head 来获取
实例代码,封装如下
// 获取server返回头信息 function get_response_header($url='https://mimvp.com') { $res_headers = array(); try { $res_headers = get_headers($url, 1); // 0 - 不格式化; 1 - 格式化 if($res_headers == false) { // 返回结果失败 $retval = null; $res = null; $res_array = array(); $cmd = sprintf("/usr/bin/curl -k --head '%s'", $url); echo '<br><br> cmd : ' . $cmd; // exec $res = exec($cmd, $res_array, $retval); echo "<br><br> exec result:"; var_dump($retval); // 0 (返回的状态, 0 - 成功, 非零 - 失败) var_dump($res); // '' var_dump($res_array); // 返回结果数组 $idx = 0; foreach($res_array as $line) { // $res_array 转成 $res_headers $line = str_replace(":", ":", trim($line)); if($idx == 0 && $line != "") { // 处理第一行的状态 $res_headers[0] = $line; } if(strstr($line, ":") != "") { $key = trim(explode(":", $line)[0]); $val = trim(explode(":", $line)[1]); $res_headers[$key] = $val; } else if($idx >= 2 && $line != "") { $res_headers[$idx] = $line; } $idx += 1; } } } catch (Exception $e) { var_dump($e); } var_dump($res_headers); return $res_headers; }
运行结果
1)正常时,执行 get_headers() ,返回结果如下:
/Users/homer/Downloads/myCode/workspace/navi_client/api/header2.php:67: array (size=6) 0 => string 'HTTP/1.1 200 OK' (length=15) 'Server' => string 'nginx' (length=5) 'Date' => string 'Tue, 26 Dec 2017 02:38:59 GMT' (length=29) 'Content-Type' => string 'text/html; charset=UTF-8' (length=24) 'Connection' => string 'close' (length=5) 'Vary' => array (size=4) 0 => string 'Accept-Encoding' (length=15) 1 => string 'Accept-Encoding' (length=15) 2 => string 'mimvp-home-bj2' (length=14) 3 => string 'mimvp-homes-bj2' (length=15)
2)失败时,执行 curl --head ,返回结果如下:
/Users/homer/Downloads/myCode/workspace/navi_client/api/header2.php:67: array (size=5) 0 => string 'HTTP/2 200' (length=10) 'server' => string 'nginx' (length=5) 'date' => string 'Tue, 26 Dec 2017 02' (length=19) 'content-type' => string 'text/html; charset=UTF-8' (length=24) 'vary' => string 'mimvp-homes-bj2' (length=15)
在 shell 执行cmd命令,查看其结果
$ /usr/bin/curl -k --head 'https://mimvp.com' HTTP/1.1 200 OK Server: nginx Date: Tue, 26 Dec 2017 02:45:52 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding Vary: Accept-Encoding Vary: mimvp-home-bj2 Vary: mimvp-homes-bj2
可见,curl --head 基本补充了 get_headers 执行失败时获取服务器端头信息的功能
还有一点瑕疵就是 Vary 变量数组处理的不完美,完整代码量大,在此不给出了,请自行判断实现之
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2018-06-01 05:34:33
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!
转载注明: PHP 执行外部命令函数:exec()、system()、passthru()、shell_exec()、popen() (米扑博客)