在 PHP 7 中,exec 是一个用于执行外部系统命令的核心函数。它在 Web 开发中非常强大,但同时也伴随着较高的安全风险。

📌 exec() 函数基本用法

exec 函数的语法结构如下: exec(string $command, array &$output = null, int &$result_code = null): string | false

它包含三个参数:

  1. $command(必填):你要执行的系统命令字符串。
  2. $output(可选):一个数组。如果提供了这个参数,命令执行的每一行输出都会被填充到这个数组中。
  3. $result_code(可选):一个变量。如果提供,命令执行后的返回状态码(通常成功为 0)会被写入此变量。

返回值:默认情况下,exec 只会返回命令执行结果的最后一行字符串

基础代码示例:

  1. <?php
  2. // 执行查看当前目录文件的命令
  3. exec('ls -l', $output, $retval);
  4. echo "命令执行状态码: " . $retval . "\n";
  5. echo "命令输出的最后一行: " . $output[count($output) - 1] . "\n";
  6. echo "完整输出内容:\n";
  7. print_r($output);
  8. ?>

⚠️ PHP 7 中使用 exec 的常见限制与风险

在 PHP 7 环境中使用 exec,你最常遇到的其实是以下两个问题:

1. 函数被禁用(disable_functions) 出于安全考虑,绝大多数生产环境(尤其是虚拟主机或共享主机)都会在 php.ini 配置文件中通过 disable_functions 指令禁用 exec

  • 如何排查:你可以通过 phpinfo() 查看 disable_functions 这一项,看看里面是否包含 exec
  • 如何解决:如果是你自己的服务器(如独立部署的 Nginx+PHP-FPM),可以修改对应的 php.ini 文件,从 disable_functions 列表中移除 exec,然后重启 PHP-FPM 服务使其生效。

2. 安全风险(命令注入) 绝对不要直接将未经处理的用户输入拼接到 exec 的命令中。

  • 错误示范exec("ls -l " . $_GET['dir']); 如果用户输入 dir; rm -rf /,将会导致灾难性的后果。
  • 正确做法:必须使用 escapeshellarg()escapeshellcmd() 对用户输入进行转义过滤。
    1. <?php
    2. $dir = $_GET['dir'];
    3. // 使用 escapeshellarg 将参数转义,防止恶意命令注入
    4. $safe_dir = escapeshellarg($dir);
    5. exec("ls -l " . $safe_dir, $output);
    6. ?>

🔄 exec 与其他命令执行函数的区别

PHP 提供了多个执行系统命令的函数,根据需求选择合适的非常重要:

函数名 特点与区别
exec() 不直接输出结果,返回最后一行。可通过数组获取全部输出和状态码。
system() 直接输出命令结果到浏览器,并返回最后一行。
shell_exec() 返回完整的输出结果(字符串),无法获取状态码。
passthru() 直接输出原始结果(适合二进制数据,如图片流),可获取状态码。

如果你需要在 PHP 7 中执行一些复杂的后台任务,或者发现 exec 始终受限,也可以考虑使用更现代、更安全的替代方案,例如 Symfony Process 组件,它提供了更好的跨平台兼容性和进程控制能力。