PHP项目命令与动作

wen PHP项目 1

本文目录导读:

PHP项目命令与动作

  1. 命令行脚本执行
  2. Laravel Artisan命令
  3. SSH远程命令执行
  4. 队列与异步任务
  5. 定时任务(Cron Job)
  6. 在Web环境中安全执行
  7. 异步命令处理
  8. 命令日志记录
  9. 最佳实践

我来帮您梳理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项目中常用的命令与动作处理方式,根据具体需求选择合适的方法。

抱歉,评论功能暂时关闭!