在 PHP 7 中,exec 是一个用于执行外部系统命令的核心函数。它在 Web 开发中非常强大,但同时也伴随着较高的安全风险。
📌 exec() 函数基本用法
exec 函数的语法结构如下:
exec(string $command, array &$output = null, int &$result_code = null): string | false
它包含三个参数:
- $command(必填):你要执行的系统命令字符串。
- $output(可选):一个数组。如果提供了这个参数,命令执行的每一行输出都会被填充到这个数组中。
- $result_code(可选):一个变量。如果提供,命令执行后的返回状态码(通常成功为 0)会被写入此变量。
返回值:默认情况下,exec 只会返回命令执行结果的最后一行字符串。
基础代码示例:
<?php// 执行查看当前目录文件的命令exec('ls -l', $output, $retval);echo "命令执行状态码: " . $retval . "\n";echo "命令输出的最后一行: " . $output[count($output) - 1] . "\n";echo "完整输出内容:\n";print_r($output);?>
⚠️ 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()对用户输入进行转义过滤。<?php$dir = $_GET['dir'];// 使用 escapeshellarg 将参数转义,防止恶意命令注入$safe_dir = escapeshellarg($dir);exec("ls -l " . $safe_dir, $output);?>
🔄 exec 与其他命令执行函数的区别
PHP 提供了多个执行系统命令的函数,根据需求选择合适的非常重要:
| 函数名 | 特点与区别 |
|---|---|
| exec() | 不直接输出结果,返回最后一行。可通过数组获取全部输出和状态码。 |
| system() | 直接输出命令结果到浏览器,并返回最后一行。 |
| shell_exec() | 返回完整的输出结果(字符串),无法获取状态码。 |
| passthru() | 直接输出原始结果(适合二进制数据,如图片流),可获取状态码。 |
如果你需要在 PHP 7 中执行一些复杂的后台任务,或者发现 exec 始终受限,也可以考虑使用更现代、更安全的替代方案,例如 Symfony Process 组件,它提供了更好的跨平台兼容性和进程控制能力。
