Powershell, модуль Posh-SSH: Как должно работать чтение потока в Posh-SSH?

Вопрос или проблема

Я пытаюсь понять, как чтение потока должно работать в Posh-SSH, чтобы я мог собрать функцию “ожидание-действие”, чтобы скрипт продолжался только после выполнения удаленной команды.

Цель кода, показанного ниже, заключается в том, чтобы запустить “yum update” на удаленной системе (Linux, CentOS 7), затем мониторить поток, чтобы определить, когда удаленная команда завершена, а затем перейти к следующей строке скрипта. Это работает “иногда”, но не последовательно.

Этот код успешно настраивает новое SSH-соединение и определяет поток:

$hostIP = "IP_удаленного_сервера_Linux"
$centosCreds = "Мой_объект_учетных_данных"
$pemFile = "Мой_Pem_файл"
New-SSHSession -ComputerName $hostIP -Port 22 -Credential $centosCreds -KeyFile $pemFile -ConnectionTimeout 120 -OperationTimeout 120 -AcceptKey
$stream = New-SSHShellStream -Index 0

Выполнение удаленной команды через новый поток достаточно просто:

Invoke-SSHStreamShellCommand -ShellStream $stream -Command "yum update"

Запуск следующего во время выполнения команды Invoke-SSHStreamShellCommand (yum update) возвращает фрагмент вывода удаленной команды, как ожидалось:

$stream.Read()

Однако, как только “yum update” завершен, чтение потока возвращает только пустое значение. Информация, которую я смог найти в интернете, указывает на то, что чтение потока должно возвращать строку приглашения командной строки удаленной системы, но это, похоже, не так.

Поскольку значение, возвращаемое при чтении после завершения команды, пустое, цикл “ожидание-действие”, который я пытаюсь собрать, не работает последовательно:

$promptString = "Строка_приглашения_команды_удаленной_системы"
$streamOut = $stream.Read()
while ($streamOut -notlike "*$promptString*") {
    Start-Sleep -s 1
    $streamOut = $stream.Read()
}

Я не уверен, что я упускаю здесь – документация ограничена, и мне не удалось найти много других примеров чтения потока Posh-SSH, которые соответствуют поведению, которое я наблюдаю.

Буду признателен за любые рекомендации или предложения.

Спасибо.

Этот пост очень старый, но на него так и не ответили. Я никогда не видел, чтобы stream.Read() возвращал приглашение командной строки. Возможно, какая-то модификация этого должна сработать:

$promptString = "Строка_приглашения_команды_удаленной_системы"
$streamOut = $stream.Read()
while (($streamOut).length -ne 0) {
    Start-Sleep -s 1
    $streamOut = $stream.Read()
}

Другие варианты – использовать -match и искать фразу, которую он использует, когда завершено, или спать дольше, а затем проверять журнал yum для подтверждения обновления. Любое из этих решений, вероятно, выполнит задачу.

$stream.Read() производит одну строку с переносами строки /r/n.

Мне пришлось поместить $stream.Read() в переменную и разбить на массив. Затем сканировать каждую строку.

В общем, я написал набор функций для этого. Все еще тестирую.

Ответ или решение

Чтение потоков в модуле Posh-SSH: Полное руководство

Модуль Posh-SSH является мощным инструментом для работы с удалёнными системами через SSH в PowerShell. Ваша задача по реализации функции ожидания завершения действия (wait-action) при выполнении команды на удалённой Linux-системе, такой как yum update, требует детального понимания того, как работает чтение потоков в Posh-SSH.

Основные моменты работы со стримами

Когда вы производите вызов New-SSHShellStream, создаётся новый поток оболочки, что позволяет отправлять команды и получать вывод от удалённой системы. После успешного выполнения команды Invoke-SSHStreamShellCommand, вы ожидаете получения вывода, который позволит определить конечный статус выполнения команды.

Проблема с пустыми значениями

По вашему описанию, проблема заключается в том, что после выполнения команды yum update метод $stream.Read() возвращает пустое значение, что затрудняет проверку завершенности команды. Это может быть связано с особенностями работы с потоками в Posh-SSH. Важно понимать, что после завершения команды, поток возвращает не только вывод, который вы ожидаете, но и может завершать линию управления.

Пример реализации функции ожидания

Для реализации вашего поведения, рассмотрим несколько подходов:

  1. Чтение вывода и ожидание строки завершения: Вместо поиска конкретной строки-маршрута, стоит проверить наличие фактического вывода. Например, вывод может содержать определённые слова, указывающие на успешное завершение:

    $streamOut = $stream.Read()
    while (($streamOut).length -ne 0) {
        if ($streamOut -match "Complete|Updated") {
            break
        }
        Start-Sleep -s 1
        $streamOut = $stream.Read()
    }
  2. Использование функций обработки массивов: Для более детального анализа и разбивки строк можно воспользоваться методом .Split(), что позволит работать с каждой строкой вывода отдельно:

    $streamOut = $stream.Read()
    $lines = $streamOut -split "`r`n"
    foreach ($line in $lines) {
        if ($line -match "Complete|Updated") {
            # Действия после завершения
            break
        }
    }
  3. Проверка логов: Альтернативно, можно проверить системные логи (yum.log) после завершения операции для подтверждения факта обновления. Это обеспечит дополнительную проверку, так как некоторый вывод мог не дойти до вашего потока.

Заключение

При работе с потоками в Posh-SSH важно помнить, что вы можете сталкиваться с различными выходными данными, которые могут не всегда соответствовать ожидаемым. Оптимизация кода, использование регулярных выражений и разбивка вывода на массивы помогут вам более эффективно обрабатывать данные и ожидать завершение команд.

Это должно улучшить стабильность вашего сценария и сделать его более предсказуемым. Если у вас возникают дополнительные вопросы или проблемы, не стесняйтесь обращаться за дальнейшей помощью.

Оцените материал
Добавить комментарий

Капча загружается...