Вопрос или проблема
Я пытаюсь понять, как чтение потока должно работать в 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. Важно понимать, что после завершения команды, поток возвращает не только вывод, который вы ожидаете, но и может завершать линию управления.
Пример реализации функции ожидания
Для реализации вашего поведения, рассмотрим несколько подходов:
-
Чтение вывода и ожидание строки завершения: Вместо поиска конкретной строки-маршрута, стоит проверить наличие фактического вывода. Например, вывод может содержать определённые слова, указывающие на успешное завершение:
$streamOut = $stream.Read() while (($streamOut).length -ne 0) { if ($streamOut -match "Complete|Updated") { break } Start-Sleep -s 1 $streamOut = $stream.Read() }
-
Использование функций обработки массивов: Для более детального анализа и разбивки строк можно воспользоваться методом
.Split()
, что позволит работать с каждой строкой вывода отдельно:$streamOut = $stream.Read() $lines = $streamOut -split "`r`n" foreach ($line in $lines) { if ($line -match "Complete|Updated") { # Действия после завершения break } }
-
Проверка логов: Альтернативно, можно проверить системные логи (
yum.log
) после завершения операции для подтверждения факта обновления. Это обеспечит дополнительную проверку, так как некоторый вывод мог не дойти до вашего потока.
Заключение
При работе с потоками в Posh-SSH важно помнить, что вы можете сталкиваться с различными выходными данными, которые могут не всегда соответствовать ожидаемым. Оптимизация кода, использование регулярных выражений и разбивка вывода на массивы помогут вам более эффективно обрабатывать данные и ожидать завершение команд.
Это должно улучшить стабильность вашего сценария и сделать его более предсказуемым. Если у вас возникают дополнительные вопросы или проблемы, не стесняйтесь обращаться за дальнейшей помощью.