Как запускать команды на SSH-сервере в C#?

Мне нужно выполнить это действие, используя код C#:

  1. откройте putty.exe в фоновом режиме (это как окно cmd)
  2. войти на удаленный хост, используя его IP-адрес
  3. введите имя пользователя и пароль
  4. выполнить несколько команд одну за другой.
  5. выполните другую команду, которая получит ответ, сообщающий мне, что команды, которые я запускал до этого, выполнялись успешно

Поэтому я пытаюсь сделать это так:

ProcessStartInfo proc = new ProcessStartInfo() 
{
     FileName = @"C:\putty.exe",
     UseShellExecute = true, //I think I need to use shell execute ?
     RedirectStandardInput = false,
     RedirectStandardOutput = false,
     Arguments = string.Format("-ssh {0}@{1} 22 -pw {2}", userName, hostIP, password)
     ... //How do I send commands to be executed here ?
};
Process.Start(proc);

2 ответа

Решение

Вы можете попробовать https://sshnet.codeplex.com/. При этом вам не понадобится замазка или окно вообще. Вы можете получить ответы тоже. Это будет выглядеть как это.

SshClient sshclient = new SshClient("172.0.0.1", userName, password);    
sshclient.Connect();
SshCommand sc= sshclient .CreateCommand("Your Commands here");
sc.Execute();
string answer = sc.Result;

Изменить: Другой подход будет использовать shellstream.

Создайте ShellStream один раз как:

ShellStream stream = sshclient.CreateShellStream("customCommand", 80, 24, 800, 600, 1024);

Тогда вы можете использовать такую ​​команду:

  public StringBuilder sendCommand(string customCMD)
    {
        StringBuilder answer;

        var reader = new StreamReader(stream);
        var writer = new StreamWriter(stream);
        writer.AutoFlush = true; 
        WriteStream(customCMD, writer, stream);
        answer = ReadStream(reader);
        return answer;
    }

private void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
    {
        writer.WriteLine(cmd);
        while (stream.Length == 0)
        {
            Thread.Sleep(500);
        }
    }

private StringBuilder ReadStream(StreamReader reader)
    {
        StringBuilder result = new StringBuilder();

        string line;
        while ((line = reader.ReadLine()) != null)
        {
            result.AppendLine(line);
        }
        return result;
    }

Пока работает ответ @LzyPanda, используя канал SSH "shell" (SshClient.CreateShellStream), пусть только интерактивный терминал, не очень хорошая идея для автоматизации выполнения команд. Вы получаете много побочных эффектов, таких как командные строки, последовательности ANSI, интерактивное поведение некоторых команд и т. Д.

Для автоматизации используйте SSH "exec" канал (SshClient.CreateCommand):

using (var command = ssh.CreateCommand("command"))
{
    Console.Write(command.Execute());
}

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

Хотя, если команды зависят друг от друга (первая команда изменила среду, например, переменные, которые используются последними командами), вы должны выполнить их в пределах одного канала. Используйте для этого синтаксис оболочки, например && или же ;:

using (var command = ssh.CreateCommand("command1 && command2"))
{
    Console.Write(command.Execute());
}

Если вам нужно постоянно читать команды вывода, используйте:

using (var command = ssh.CreateCommand("command"))
{
    var asyncExecute = command.BeginExecute();
    command.OutputStream.CopyTo(Console.OpenStandardOutput());
    command.EndExecute(asyncExecute);
}

Вы также можете использовать ExtendedOutputStream, который содержит как stdout, так и stderr. См. Мониторинг вывода команды SSH.NET в реальном времени.


К сожалению, реализация канала "exec" в SSH.NET не позволяет доказать ввод команды. В этом случае вам нужно будет обратиться к каналу "shell", пока это ограничение не будет устранено.

Другие вопросы по тегам