本文目录导读:

我来帮您梳理PHP项目中常见的命令与动作使用方式。
命令行脚本执行
基础命令执行
// 执行shell命令
$output = shell_exec('ls -la');
echo $output;
// 更推荐的方式
exec('git pull origin main', $output, $returnCode);
if ($returnCode === 0) {
echo "执行成功";
}
// 获取完整输出
$output = [];
$returnCode = 0;
exec('php artisan migrate', $output, $returnCode);
使用Symfony Process组件
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
$process = new Process(['php', 'artisan', 'cache:clear']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
echo $process->getOutput();
Laravel Artisan命令
创建自定义Artisan命令
// app/Console/Commands/BackupDatabase.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class BackupDatabase extends Command
{
protected $signature = 'db:backup
{--database=mysql : 数据库连接}
{--path= : 备份路径}';
protected $description = '备份数据库';
public function handle()
{
$database = $this->option('database');
$path = $this->option('path') ?? storage_path('backups');
$this->info("开始备份数据库...");
// 执行备份命令
$command = sprintf(
'mysqldump -u%s -p%s %s > %s/backup_%s.sql',
config("database.connections.{$database}.username"),
config("database.connections.{$database}.password"),
config("database.connections.{$database}.database"),
$path,
date('Y-m-d_H-i-s')
);
exec($command, $output, $returnCode);
if ($returnCode === 0) {
$this->info('备份成功!');
} else {
$this->error('备份失败');
}
}
}
命令注册
// app/Console/Kernel.php
protected $commands = [
Commands\BackupDatabase::class,
];
SSH远程命令执行
use phpseclib3\Net\SSH2;
class RemoteCommandExecutor
{
public function executeCommand($host, $username, $password, $command)
{
$ssh = new SSH2($host);
if (!$ssh->login($username, $password)) {
throw new \Exception('登录失败');
}
return $ssh->exec($command);
}
public function deploy()
{
$executor = new RemoteCommandExecutor();
$commands = [
'cd /var/www/project',
'git pull origin main',
'composer install --no-dev',
'php artisan migrate',
'php artisan cache:clear',
'php artisan queue:restart'
];
$output = [];
foreach ($commands as $command) {
$output[] = $executor->executeCommand(
'server.example.com',
'deployer',
'password',
$command
);
}
return $output;
}
}
队列与异步任务
// 创建任务
php artisan make:job ProcessPodcast
// 任务类
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
// 执行业务逻辑
exec('ffmpeg -i input.mp3 output.mp3');
}
}
// 分发任务
ProcessPodcast::dispatch($podcast)->onQueue('processing');
// 命令式执行队列
php artisan queue:work --queue=high,default
定时任务(Cron Job)
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 每日备份
$schedule->command('db:backup')
->daily()
->at('02:00')
->sendOutputTo(storage_path('logs/backup.log'));
// 每小时清理
$schedule->call(function () {
File::cleanDirectory(storage_path('temp'));
})->hourly();
// 执行外部命令
$schedule->exec('node cleanup.js')->daily();
}
在Web环境中安全执行
class AdminController extends Controller
{
public function executeCommand(Request $request)
{
// 权限检查
if (!auth()->user()->isAdmin()) {
abort(403);
}
$command = $request->input('command');
// 白名单验证
$allowedCommands = ['git pull', 'composer install', 'cache:clear'];
if (!in_array($command, $allowedCommands)) {
return response()->json(['error' => '不允许的命令'], 403);
}
// 安全执行
try {
$output = [];
$returnCode = 0;
exec($command . ' 2>&1', $output, $returnCode);
return response()->json([
'status' => $returnCode === 0 ? 'success' : 'error',
'output' => implode("\n", $output)
]);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
}
异步命令处理
use React\EventLoop\Factory;
use React\ChildProcess\Process;
class AsyncCommandHandler
{
public function runAsync($command)
{
$loop = Factory::create();
$process = new Process($command);
$process->on('exit', function ($exitCode) {
echo "进程退出,退出码: " . $exitCode;
});
$loop->addTimer(0.001, function () use ($process) {
$process->start();
});
$loop->run();
}
}
命令日志记录
class CommandLogger
{
public static function log($command, $output, $status)
{
Log::channel('commands')->info('命令执行', [
'command' => $command,
'output' => $output,
'status' => $status,
'user' => auth()->user()?->id,
'ip' => request()->ip(),
'execution_time' => microtime(true) - LARAVEL_START
]);
}
}
最佳实践
安全注意事项
// 转义命令
$safeCommand = escapeshellcmd($userInput);
$safeArg = escapeshellarg($userArg);
// 限制执行环境
putenv('PATH=/usr/local/bin:/usr/bin');
错误处理
try {
exec($command, $output, $returnCode);
if ($returnCode !== 0) {
throw new CommandException(
"命令执行失败: $command",
$returnCode
);
}
} catch (CommandException $e) {
// 记录错误
Log::error($e->getMessage());
// 通知管理员
Notification::route('mail', 'admin@example.com')
->notify(new CommandFailed($e));
}
这些是PHP项目中常用的命令与动作处理方式,根据具体需求选择合适的方法。