Отправка команд в сессию SSH в PowerShell и получение вывода в TextBox - PullRequest
4 голосов
/ 21 октября 2019

Мне нужно отправить список команд на несколько устройств. Для каждого IP-адреса откройте SSH-соединение с заданными учетными данными из текстовых полей Пользователь и Пароль , выполните все команды и верните вывод в текстовое поле Выход .

Screenshot of Window containing textboxes for credetials, IPs, commands and output

Обычно я бы использовал

plink.exe -ssh admin@172.16.17.18 -pw PassW0rd "command"

К сожалению, удаленный хост не позволяет мне сделать это:

Sent password
Access granted
Opening session as main channel
Opened main channel
Server refused to start a shell/command
FATAL ERROR: Server refused to start a shell/command

Однако, если я подключаюсь без передачи команды:

Sent password
Access granted
Opening session as main channel
Opened main channel
Allocated pty (ospeed 38400bps, ispeed 38400bps)
Started a shell/command


Welcome to XXX
System_Name>#

Теперь я могу набирать свои команды и выполнять их. Я попробовал PoshSSH, который позволяет мне подключаться, но время ожидания любой команды истекло.

Я разбил строки из IP- и командных блоков на строковые массивы и создал циклы. Затем я попробовал несколько подходов с Start-Job и SystemDiagnostics.Process*, но безуспешно. Теперь я немного невежественен и буду признателен за любую помощь:

for ($a=0; $a -lt $IPArray.Length; $a++){
  # Open an interactive Session with plink like
  # plink.exe -ssh ' + $User + '@' + $IPArray[$a] + ' -pw ' + $Passwd
  for ($b=0; $b -lt $CommandArray.Length; $b++){
    # Send $CommandArray[$b] to plink-Session
    # Wait for command to finish
    # Read output and send it to the textbox
  }
}

Редактировать: Благодаря ответу Мартина Прикрыла я на шаг впереди:

for ($a=0; $a -lt $IPArray.Length; $a++){
  $User = $UserTextBox.text
  $IP = $IPArray[$a]
  # $Passwd = $PwdTextBox.Text
  $Outputtext= $Outputtext + "~~~~~ " + $IP + " ~~~~~" + "`r`n"
  $isSession = New-SSHSession -ComputerName $IP -Credential $User
  $isStream = $isSession.Session.CreateShellStream("PS-SSH", 0, 0, 0, 0, 1000)      
  for ($b=0; $b -lt $CommandArray.Length; $b++){
    $Command = $CommandArray[$b]
    $isStream.WriteLine("$Command")
    Start-Sleep -Seconds 1
  }
  $isReturn = $isStream.Read()
  $Outputtext= $Outputtext + $isReturn + "`r`n"
  $outputBox.Text = $Outputtext
}

возвращает:

~~~~~ 172.16.17.18 ~~~~~

Welcome to XXX
System_18>#echo 1
1
System_18>#echo 2
2
System_18>#ping 8.8.8.8 
PING 8.8.8.8 56 data bytes

~~~~~ 172.16.17.19 ~~~~~


Welcome to XXX
System_19>#echo 1
1
System_19>#echo 2
2
System_19>#ping 8.8.8.8 
PING 8.8.8.8 56 data bytes

~~~~~ 172.16.17.20 ~~~~~

Welcome to XXX
System_20>#echo 1
1
System_20>#echo 2
2
System_20>#ping 8.8.8.8 
PING 8.8.8.8 56 data bytes

Теперь мне нужно выполнить две вещи:

  1. Получить учетные данные из соответствующих полей ввода (В настоящее время мне нужно ввести пароль один раз для каждогоIP)

    Готово:

    $User = $UserTextBox.text
    $Passwd = ConvertTo-SecureString $PwdTextBox.Text -AsPlainText -Force
    $SSHCred = New-Object System.Management.Automation.PSCredential -ArgumentList ($User, $Passwd)
    # ...
    $isSession = New-SSHSession -ComputerName $IP -Credential $SSHCred
    
  2. Дождитесь завершения команды до отправки следующей. (В настоящее время он просто ждет 1 секунду)

Однако я рад, что удаленные хосты теперь общаются со мной, по крайней мере. Спасибо.

Должен ли я открыть новые вопросы, если мне понадобится дополнительная помощь по сценарию или продолжить регистрировать ход выполнения, здесь?

1 Ответ

0 голосов
/ 21 октября 2019

Вы, очевидно, подключаетесь к какому-то «устройству», а не к полному серверу. Внедренные реализации SSH обычно не реализуют канал exec SSH. Вы должны использовать канал «shell» (что иначе не рекомендуется для автоматизации команд).

С помощью Plink вы можете достичь этого, записав «команду» на вход Plink, вместо использования переключателя -m.

См. Также Выполнение команды с использованием Plink не работает,но в PuTTY .


Хотя вам не следует запускать внешнее приложение для реализации SSH. Используйте собственную реализацию .NET SSH, например SSH.NET . Псевдокод для выполнения команды с SSH.NET в канале «shell»:

var client = new SshClient(...);
client.Connect();
var shell = client.CreateShellStream(...);
shell.WriteLine("command");
var output = shell.Read();

Канал «shell» - это черный ящик с входом и выходом. Не существует надежного способа использовать его для выполнения команды, чтения ее выходных данных и выполнения других команд. У вас нет API, чтобы сказать, когда выполнение команды закончилось. Вот почему я написал выше, что канал "shell" не рекомендуется для автоматизации команд. Все, что вы можете сделать, это проанализировать выходные данные оболочки и найти командную строку вашего устройства: System_20>.

...