国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

整理分享Workerman中利用popen實(shí)現(xiàn)多進(jìn)程web ssh

Jinson

來源于群里兔子大佬 @chaz6chez 的分享,自己整理測試了下。

起源

群友詢問如何進(jìn)程異步執(zhí)行命令行任務(wù),且有通知機(jī)制,想用來做web ssh,兔子大佬指導(dǎo)可以通過 popen 來實(shí)現(xiàn):

群友討論

實(shí)踐

測試使用的是 workerman5.0 版本,基于兔佬提供是偽代碼進(jìn)行調(diào)整,使用 websocket 交互

在項(xiàng)目根目錄新建 start.php 文件,代碼如下:

<?php

require_once __DIR__ . '/vendor/autoload.php';

date_default_timezone_set('Asia/Shanghai');

//進(jìn)程池類
class ProcessPool
{
    private array $processes = [];
    public int $maxProcesses;

    public function __construct($maxProcesses = 5)
    {
        $this->maxProcesses = $maxProcesses;
    }

    //添加進(jìn)程 popen打開的進(jìn)程執(zhí)行完會退出,不做復(fù)用
    public function add(string $command)
    {
        $process           = popen($command, 'r');
        $this->processes[] = $process;
        return $process;
    }

    // 釋放進(jìn)程
    public function releaseProcess($process): void
    {
        $key = array_search($process, $this->processes);
        if ($key !== false) {
            unset($this->processes[$key]); // 從活動進(jìn)程池移除
        }
    }

    // 獲取池中的所有進(jìn)程數(shù)量
    public function processCount(): int
    {
        return count($this->processes);
    }
}

// 創(chuàng)建一個(gè)websocket Worker
$task = new \Workerman\Worker("websocket://0.0.0.0:3232");

// 初始化進(jìn)程池
$processPool = new ProcessPool(5);

// 添加定時(shí)器,每秒打印進(jìn)程數(shù)
$task->onWorkerStart = function (\Workerman\Worker $worker) use ($processPool) {
    \Workerman\Timer::add(1, function () use ($processPool) {
        var_dump('[' . date('H:i:s') . '] 活動進(jìn)程數(shù):' . $processPool->processCount());
    });
};

$task->onMessage = function (Workerman\Connection\TcpConnection $connection, $str) use ($processPool) {
    $data = json_decode($str, JSON_OBJECT_AS_ARRAY);
    $command = $data['command'] ?? '';
    if (empty($command)) {
        return $connection->send('無效命令');
    }

    //超過最大進(jìn)程數(shù)時(shí)阻塞等待退出
    if ($processPool->processCount() >= $processPool->maxProcesses) {
        return $connection->send('使用進(jìn)程數(shù)已達(dá)最大數(shù),等待中...');
    }

    // 獲取一個(gè)進(jìn)程資源
    $process = $processPool->add($command);
    if (is_resource($process)) {

        // 創(chuàng)建讀事件
        \Workerman\Worker::$globalEvent->onReadable($process, function ($pipe) use ($connection, $process, $processPool) {
            // 讀取進(jìn)程輸出
            $output = fread($pipe, 8192);
            if ($output === false || feof($pipe)) {
                // 進(jìn)程結(jié)束,釋放資源
                fclose($pipe);
                $processPool->releaseProcess($pipe);
                $connection->send("進(jìn)程結(jié)束.");
                \Workerman\Worker::$globalEvent->offReadable($process);
            } else {
                // 將輸出發(fā)送給客戶端
                $connection->send($output);
            }
        });

        return true;

    } else {
        return $connection->send("服務(wù)繁忙,請稍后重試.");
    }
};

\Workerman\Worker::runAll();

測試

項(xiàng)目根目錄新建一個(gè) command.php文件,用于測試

<?php

for ($i = 0; $i < 5; $i++) {
    sleep(1);
    echo '測試' . $i . PHP_EOL;
}

php start.php start 啟動項(xiàng)目,前端使用 【W(wǎng)ebSocket 測試工具】進(jìn)行連接,發(fā)送消息執(zhí)行命令:/usr/bin/php8.2 command.php

websocket 調(diào)試工具

執(zhí)行 pstree -ap | grep -C 20 /usr/bin/php8.2,可以看到有 5 個(gè)進(jìn)程在跑,popen 打開的command.php進(jìn)程執(zhí)行完成后,就會自動退出。

進(jìn)程查看

總結(jié)

通過 workerman 和 popen 可以異步進(jìn)程執(zhí)行命令,前端再搭配 xterm.js 就可以做 web ssh了;當(dāng)然還可以有很多適用的場景,比如用 workerman 拉起think-queue進(jìn)程等等,自行拓展...

491 2 0
2個(gè)評論

Tinywan

不錯(cuò)

  • 暫無評論
hunma

很強(qiáng)

  • 暫無評論

Jinson

710
積分
0
獲贊數(shù)
0
粉絲數(shù)
2023-06-06 加入
??