detain/sshpool 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

detain/sshpool

Composer 安装命令:

composer require detain/sshpool

包简介

SSH command queue and connection pool runs tons of commands on a ssh host concurrently with completion callback.

README 文档

README

License: GPL v3

detain/sshpool is a small PHP library for running many shell commands on a single SSH host concurrently. It maintains one SSH session, opens multiple ssh2_exec channels in parallel up to a configurable cap, collects each command's stdout / stderr / exit status, and fires a per-command callback on completion. Commands can be queued while the pool is already running, automatic retries with a back-off delay are supported, and per-command timeouts kill long-running work.

Requirements

  • PHP 8.0+
  • The ext-ssh2 PHP extension
  • An SSH host you can authenticate to with a key pair

Password authentication is not currently wired through; the supported path is public/private key authentication via ssh2_auth_pubkey_file.

Installation

composer require detain/sshpool

If you do not already have ext-ssh2 installed:

# Debian / Ubuntu
sudo apt-get install php-ssh2

# RHEL / Alma / Rocky
sudo dnf install php-pecl-ssh2

Quick Start

require 'vendor/autoload.php';

use Detain\SshPool\SshPool;

$pool = new SshPool(
    'example.com',          // host
    22,                     // port
    'deploy',               // ssh user
    '',                     // password (unused — pubkey auth)
    '/home/me/.ssh/id_rsa.pub',
    '/home/me/.ssh/id_rsa'
);

$pool->setMaxThreads(10);
$pool->setMaxRetries(2);

foreach (['uptime', 'df -h', 'free -m'] as $cmd) {
    $pool->addCommand(
        $cmd,
        null,                               // auto id
        ['command' => $cmd],                // user data passed to callback
        function ($cmd, $id, $data, $exit, $stdout, $stderr) {
            echo "[{$id}] {$cmd} (exit {$exit}):\n{$stdout}\n";
            if ($stderr !== '') {
                fwrite(STDERR, "[{$id}] stderr: {$stderr}\n");
            }
        },
        30                                  // 30s timeout
    );
}

$pool->run();

Usage Patterns

One-shot synchronous command

For a single command where you want a synchronous result rather than a callback, use runCommand():

$result = $pool->runCommand('hostname');
// $result === ['cmd' => 'hostname', 'exitStatus' => 0, 'out' => '...', 'err' => '']

runCommand() returns false if the channel cannot be opened.

Adding commands while the pool is running

addCommand() is safe to call from inside a completion callback. New commands join $cmdQueue and the run loop picks them up on its next iteration.

$pool->addCommand('first', null, null, function ($cmd, $id, $data, $exit) use ($pool) {
    if ($exit === 0) {
        // Chain a follow-up command.
        $pool->addCommand('second');
    }
});
$pool->run();

Non-blocking single iteration

run(true) performs one polling iteration (start any newly-available commands, drain finished output, promote any due retries) and returns. This is useful when you want to integrate the pool into your own event loop.

while (!$done) {
    $done = $pool->run(true);
    // ... do other work ...
}

Custom SSH connection methods

ssh2_connect() accepts an algorithm/method override array. Pass it through the constructor's seventh argument when, for example, you need to whitelist a deprecated host key algorithm against a legacy server:

$pool = new SshPool(
    $host, 22, $user, '', $pub, $priv,
    ['hostkey' => 'ssh-rsa']
);

Configuration

Setter Default Effect
setMaxThreads(int) 50 Maximum number of channels open concurrently. Clamped to >= 1.
setMaxRetries(int) 0 Retry attempts on a non-zero exit status (or undersized output). 0 disables retry.
setWaitRetry(int) 15 Seconds to wait before promoting a retry back into the run queue.
setMinConfigSize(int) 0 Minimum stdout byte count required to consider a command successful. 0 disables.
$pollInterval (public int) 25000 Microseconds between run-loop polls in blocking mode.

Public API

new SshPool(
    string $host,
    int $port,
    string $user,
    string $pass,
    string $pubKey,
    string $privKey,
    array $methods = []
);

string addCommand(
    string $cmd,
    ?string $id = null,
    mixed $data = null,
    ?callable $callback = null,
    int $timeout = 0
);

bool run(bool $once = false);
array|false runCommand(string $cmd);

void connect();
void disconnect();
resource|null getConnection();

Callback signature

function (
    string $cmd,
    string $id,
    mixed  $data,        // user data passed to addCommand()
    int    $exitStatus,  // -1 if unknown / timed out
    string $stdout,
    string $stderr
): void;

Retry Semantics

A command is considered failed (and eligible for retry) when either:

  • its exit status is non-zero, or
  • minConfigSize > 0 and strlen(stdout) < minConfigSize.

Failed commands are deferred for waitRetry seconds, then promoted back into the run queue. The original timeout is preserved across retries. After maxRetries attempts the completion callback is invoked with the most recent exit status.

Timeouts

When addCommand($cmd, ..., $timeout) is given a non-zero $timeout, the run loop closes the command's streams once time() - start_time > $timeout. The callback is invoked just like any other completion. If a real exit status was not yet observed, the command is reported with exitStatus = -1.

The metadata property captures the actual duration and a boolean timed_out flag per id:

$pool->metadata['my-id'] === [
    'exit_status' => -1,
    'duration'    => 30,
    'timed_out'   => true,
];

Development

composer install
./vendor/bin/phpunit              # run the test suite
./vendor/bin/phpunit --filter Foo # run one test
./vendor/bin/phpunit --coverage-text

The tests use a FakeSshPool fixture (tests/Fixtures/FakeSshPool.php) that bypasses ext-ssh2 so the queue / callback / retry logic is verified without needing a live SSH server.

License

GPL-3.0. See LICENSE.

Author

Joe Huss · detain@interserver.net

detain/sshpool 适用场景与选型建议

detain/sshpool 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 1.71k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2023 年 01 月 27 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 detain/sshpool 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 detain/sshpool 我们能提供哪些服务?
定制开发 / 二次开发

基于 detain/sshpool 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1.71k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 9
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-3.0
  • 更新时间: 2023-01-27