Саша это я, да
Итак, в предыдущей части мы написали класс на C#, который предоставляет нам следующие методы:
  • Spawn - запуск консольного приложения. По сути это запуск всего одного единственного консольного приложения - plink. Больше для наших целей нам и не надо.
  • Expect - ожидание в выводе определенной последовательности символов. Возвращает true, если последовательность обнаружена, falst - если по истечению таймаута искомая строка не появилась.
  • Send - посылка в поток ввода процесса последовательности символов.
  • Interact - передача управления вводом и выводом пользователю.
  • Close - освобождение ресурсов.

Создадим для каждого из них удобную функцию-оболочку на PowerShell. Для того, чтобы использовать функции написанного нами класса, необходимо включить его в ps скрипте с помощью командлета Add-Type. При этом наш класс может быть уже скомпилированным в виде библиотеки. В этом случае синтаксис такой:

  1. Add-Type -Path $customDll
  2. #$customDll - путь к библиотеке

С другой стороны мы можем вставить исходный текст класса непосредственно в скрипт:

  1. $source = @"
  2. //Исходный код класса
  3. "@
  4. Add-Type -Language CSharp -TypeDefinition $source

Решите сами, какой метод вам больше по душе.
Для начала создадим объект нашего класса, с которым мы будем работать. Одного объекта нам вполне хватит. Также добавим переменную глобальной области видимости $ExpectTimeout, которая будет определять таймаут для всех вызовов метода Expect.

  1. [Zh.ZhExpect] $plink = New-Object Zh.ZhExpect
  2. [int32] $ExpectTimeout = 5
  3. #Функция Spawn-Plink. Запускает plink с заданными аргументами (адрес узла, порт, протокол, пароль, логин)
  4. function Spawn-Plink {
  5. param (
  6. [parameter(Mandatory=$true)]
  7. [alias("h")]
  8. [string]$remoteHost,
  9. [alias("p")]
  10. [string]$port = "",
  11. [alias("pr")]
  12. [string]$proto = "ssh",
  13. [alias("l")]
  14. [string]$login = "",
  15. [alias("pw")]
  16. [string]$password = ""
  17. )
  18. $argumentList = "-$proto"
  19. if ($port.length -gt 0) {
  20. $argumentList = $argumentList + " -P $port"
  21. }
  22. #Аргументы -l и -pw могут быть заданы только для ssh
  23. if ($proto -eq "ssh") {
  24. if ($login.length -gt 0) { $argumentList = $argumentList + " -l $login" }
  25. if ($password.length -gt 0) { $argumentList = $argumentList + " -pw $password" }
  26. }
  27. $argumentList = $argumentList + " " + $remoteHost
  28. $sсriрt:plink.Spawn("plink", $argumentList)
  29. }
  30. #Функция Expect. Вызывает метод plink.Expect и, если он возвращает true, выполняет заданный блок кода $action.
  31. function Expect {
  32. param(
  33. [parameter(Mandatory=$true, Position=1)]
  34. [alias("e")]
  35. [String] $ExpectString,
  36. [parameter(Position=2)]
  37. [alias("a")]
  38. [Scriptblock] $action,
  39. [alias("t")]
  40. [Int32] $timeOut = $sсriрt:ExpectTimeout
  41. [alias("ncl")]
  42. [switch]
  43. [bool] $doNotCleanReceivedText = $false
  44. )
  45. if ($sсriрt:plink.Expect($ExpectString, $timeOut, !$doNotCleanReceivedText)) {
  46. $action.Invoke()
  47. }
  48. }
  49. #Остальные функции в коментариях не нуждаются в виду своей простоты
  50. function Send {
  51. param([parameter(Mandatory=$true)]
  52. [string]$SendString
  53. )
  54. $sсriрt:plink.Send($SendString)
  55. }
  56. function Interact {
  57. param([parameter(Mandatory=$true)]
  58. [string]$stopString
  59. )
  60. $sсriрt:plink.Interact($stopString)
  61. }
  62. function Close-Plink {
  63. $sсriрt:plink.Close()
  64. }

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

  1. param (
  2. [string]$h = "",
  3. [string]$runCommandAndExit = ""
  4. )
  5. #подключаем наш файл с функциями
  6. . F:\zh\scripts\powershell\bin\Expect.ps1
  7. #
  8. Spawn-Plink -remoteHost $h -proto telnet
  9. Expect 'User name:' { Send "root`r" }
  10. Expect 'User password:' { Send "password`r" }
  11. Expect 'TERMINAL>' { Send "en`r" }
  12. Expect 'TERMINAL#' {
  13. Send "co te`r"
  14. if ($runCommandAndExit -ne "") {
  15. Start-Sleep -Seconds 1
  16. Send "$runCommandAndExitr"
  17. }
  18. }
  19. Expect 'TERMINAL(config)#' { Interact "___" }
  20. Close-Plink

  1. . F:\zh\scripts\powershell\bin\expect.ps1
  2. Spawn-Plink -proto telnet -port 4001 -remoteHost 192.168.60.60
  3. Start-Sleep -Seconds 2
  4. Send "`r`r"
  5. Expect 'user id :' { Send "sysadmin`r" }
  6. Expect 'password:' { Send "sysadmin`r" }
  7. Expect '=>' { Interact "___" }
  8. #Переходим к управлению устройством
  9. Close-Plink


Сказ про Plink, Expect и PowerShell. Предисловие
Сказ про Plink, Expect и PowerShell. Часть I: Простое решение
Сказ про Plink, Expect и PowerShell. Часть II: Нам нужен multithreading (Начало)
Сказ про Plink, Expect и PowerShell. Часть II: Нам нужен multithreading (Продолжение)

@темы: plink, Windows, Powershell, Expect