推荐使用 laravel 集成的 symfony process 组件执行系统指令,因其更安全、可控制超时、易捕获输出与错误;慎用 exec 等原生函数以防 shell 注入。

在 Laravel 中,可以通过 PHP 的原生函数(如 exec、shell_exec、system、passthru)或更安全可控的 Process 组件来调用 shell 执行系统指令。推荐使用 Laravel 自带的 Symfony Process 组件(已集成),它比裸函数更安全、可交互、易捕获输出和错误。
使用 Symfony Process(推荐)
Laravel 默认已包含 Symfony\Component\Process\Process,无需额外安装。适合需要获取返回值、控制超时、处理错误、避免 shell 注入的场景。
- 基础用法(同步执行):
$process = new Process(['ls', '-la', '/var/www']);
$process->setTimeout(60);
$process->run();
if ($process->isSuccessful()) {
echo $process->getOutput(); // 标准输出
} else {
echo $process->getErrorOutput(); // 错误输出
}
- 支持传入字符串命令(不推荐用于含用户输入的场景):
$process = Process::fromShellCommandline('git pull origin main');
$process->run();
- 异步执行(适用于队列或长时间任务):
$process = new Process(['php', 'artisan', 'queue:work']); $process->start(); // 可轮询:$process->isRunning()、$process->getOutput()
慎用 PHP 原生函数
如 shell_exec()、exec() 等函数虽简单,但存在严重风险:
- 无法自动转义参数,极易引发 shell 注入(尤其当指令含用户输入时)
- 难以控制执行时间、资源、环境变量
- 输出捕获不统一,错误流常被忽略
若必须使用,务必严格过滤输入,并避免拼接字符串命令:
// ❌ 危险示例(不要这样写)
$dir = request('path');
$output = shell_exec("ls -la " . $dir); // 用户可传入 '; rm -rf /'
// ✅ 相对安全(仅限可信固定参数)
$output = shell_exec('uptime'); // 无变量,无风险
在 Artisan 命令中调用系统指令
新建自定义命令(php artisan make:command RunSystemCommand),在 handle() 方法中使用 Process:
use Symfony\Component\Process\Process;
public function handle()
{
$process = new Process(['composer', 'install', '--no-interaction']);
$process->setWorkingDirectory(base_path());
$process->setTimeout(300)->run();
if (!$process->isSuccessful()) {
$this->error('Composer 安装失败:' . $process->getErrorOutput());
return 1;
}
$this->info('依赖安装完成');
return 0;
}
注意事项与最佳实践
- 生产环境禁用
shell_exec等函数?检查php.ini中disable_functions是否包含它们 - Web 请求中执行耗时命令易超时,建议改用队列 +
Process异步运行 - 避免以 root 权限运行 PHP 进程;确保 Web 服务器用户(如 www-data)对目标路径有足够权限
- 敏感操作(如重启服务、删除文件)务必加确认逻辑或日志审计











