MENU

PHP 程序执行函数

September 10, 2022 • Read: 1618 • PHP,编码

作为一个服务端语言,PHP不可避免会有在程序中执行外部程序的需求,那么这篇文章就总结一下 PHP 执行外部程序的函数以及需要注意的坑。

执行运算符 与 shell_exec()

通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。PHP 执行运算符,使用反引号表示。PHP 会尝试将反引号的内容当做 Shell 命令来执行,并将其输出的信息返回(既,外部程序的执行输出会返回给而不是输出到终端)。执行运算符与函数 shell_exec() 相同(可以理解为是别名的关系)。

需要注意的是,在 php.ini 中如果禁用了 shell_exec() 函数,则执行运算符也会失效。

参数说明

shell_exec(string $cmd): string || null

  • cmd 要执行的命令,与双引号一样的是,执行运算符支持解析变量。

返回值

外部程序的标准输出,如果执行过程中发生错误或进程不产生输出,则返回 null。

因为不产生输出和发生错误都会返回 null,所以,使用此函数的返回值无法检测外部程序是否执行成功,如果想获取程序执行的退出码,可以使用 exec() 函数的 return_var 参数。

例子

<?php
    // 执行运算符与 shell_exec 效果一样
    var_dump(`ls /home`);
    var_dump(shell_exec('ls /home'));
    
    // 执行错误的命令 输出 Null
    var_dump(shell_exec('ls /homes'));
?>

执行后终端输出如下内容:

dbkuaizi-alpine:/home# php test/demo.php
string(13) "project
test
"
string(13) "project
test
"
ls: /homes: No such file or directory
NULL

system

执行外部程序,并显示外部程序的输出结果。

如果运行在 PHP 服务器模块中,system() 函数还会尝试在每行输出完毕后,自动刷新 Web 服务器输出的缓存。

参数说明

system(string $command[, int &$return_var = ?]): string

  • command 要执行的命令
  • return_var 如果提供此参数,则外部命令执行后的状态将会被设置在此变量中。

返回值

成功则返回命令输出的最后一行,失败则返回 false。

若要判断命令是否成功执行,需要要判断状态码是否为 0,不要通过返回值是否等于 false 来判断执行是否成功。
因为实际测试中,执行失败的返回值是空字符串。

例子

<?php
    $a = system('ls /home',$b);
    var_dump($a,$b);
    echo '------'.PHP_EOL;
    $c = system('ll /home',$d);
    var_dump($c,$d);
?>

输出:

dbkuaizi-alpine:/home# php test/demo.php
project
test
string(4) "test"
int(0)
------
sh: ll: not found
string(0) ""
int(127)

exec

执行一个外部程序。

参数说明

exec(string $command[, array &$output = ?, int &$return_var = ?]): string
  • command 要执行的命令
  • output 如果提供了此参数,那么会用执行命令的输出填充此数组,每行输出填充数组的一个元素。需要注意的是 exec() 函数会在数组末尾追加函数,所以在多次调用的情况下,请在 exec() 函数调用,对数组使用 unset() 进行重置。
  • return_var 命令执行后的返回状态将会被写入到此变量中。

返回值

例子

<?php
    $a = exec('ls /home',$b,$c);
    var_dump($a,$b,$c);
    echo '------'.PHP_EOL;
    $a = exec('ls /usr',$b,$c);
    var_dump($a,$b,$c);
?>

输出

dbkuaizi-alpine:/home# php test/demo.php
string(4) "test"
array(2) {
  [0]=>
  string(7) "project"
  [1]=>
  string(4) "test"
}
int(0)
------
string(5) "share"
array(8) {
  [0]=>
  string(7) "project"
  [1]=>
  string(4) "test"
  [2]=>
  string(3) "bin"
  [3]=>
  string(3) "lib"
  [4]=>
  string(7) "libexec"
  [5]=>
  string(5) "local"
  [6]=>
  string(4) "sbin"
  [7]=>
  string(5) "share"
}
int(0)

由于 $output 是追加写入到数组的末尾,所以如果多次调用 一定要在调用之前 unset() 重置这个变量。

passthru

执行外部程序并显示原始输出,输出所执行命令的二进制数据。

诸如执行 pbmplus 之类的可以直接输出图像流的命令,通过设置 Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。

参数说明

passthru(string $command[, int &$result_code = null]): ?bool

  • command 要执行的命令
  • result_code 若提供此参数,则命令执行返回的状态码将会被记录到此参数中

返回值

成功返回 null,失败返回 false。

实际测试时,成功失败返回的都是 null。若要判断是否执行成功,请使用状态码判断。

例子

<?php
   $a = passthru('ls /home',$b);
   var_dump($a,$b);
   echo '------' . PHP_EOL;
   $c = passthru('ls /homec',$d);
   var_dump($c,$d)
?>

输出:

dbkuaizi-alpine:/home# php ./test/demo.php
project
test
NULL
int(0)
------
ls: /homec: No such file or directory
NULL
int(1)
dbkuaizi-alpine:/home#

需要特别注意的是,如果是在 Web 方式下执行上述的函数,当外部程序执行耗时大于 PHP 设定的超时时间,则会直接结束进程,不会有任何返回值。

参考文档:https://www.php.net/manual/zh/book.exec.php
笔记作者:两双筷子
博客:www.dbkuaizi.com

Last Modified: November 20, 2022
Leave a Comment

4 Comments
  1. 看这些代码一头雾水

    1. @鸟叔还好吧 稍微有点基础应该都能看懂

  2. @(乖) 是兄弟连出来的不

    1. @奥菲斯是 @(呵呵)