简体   繁体   中英

How to run commands on SSH server in C#?

I need to execute this action using a C# code:

  1. open putty.exe in the background (this is like a cmd window)
  2. login to a remote host using its IP address
  3. enter a user name and password
  4. execute several commands one after the other.
  5. run another command that gets a response telling me that the commands I ran before that where executed successfully

So I'm trying to do it like this:

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);

You could try https://sshnet.codeplex.com/ . With this you wouldn't need putty or a window at all. You can get the responses too. It would look sth. like this.

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;

Edit: Another approach would be to use a shellstream.

Create a ShellStream once like:

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

Then you can use a command like this:

  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;
    }

While the answer by @LzyPanda works, using an SSH "shell" channel ( SshClient.CreateShellStream ), let alone an interactive terminal, is not a good idea for automating commands execution. You get lot of side-effects from that, like command prompts, ANSI sequences, interactive behavior of some commands, etc.

For automation, use an SSH "exec" channel ( SshClient.CreateCommand ):

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

If you need to execute multiple commands, repeat the above code. You can create any number of "exec" channels for one SSH connection.

Though if the commands depend on each other (first command modified the environment, eg variables, that are used by the latter commands), you have execute them within one channel. Use a shell syntax for that, like && or ; :

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

If you need to continuously read the commands output use:

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

You can also use ExtendedOutputStream , which contains stderr. See SSH.NET real-time command output monitoring .


Unfortunately implementation of "exec" channel in SSH.NET does not allow providing an input to the command. For that use case, you will need to resort to the "shell" channel, until this limitation is solved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM