How to Run Commands on Ssh Server in C#

How to run commands on SSH server in C#?

You could try https://github.com/sshnet/SSH.NET.
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;
}

Execute multiple dependent SSH commands using SSH.NET in C#

this is what I have done and its working for me:

SshClient sshClient = new SshClient("some IP", 22, "loign", "pwd");
sshClient.Connect();

ShellStream shellStream = sshClient.CreateShellStream("xterm", 80, 40, 80, 40, 1024);

string cmd = "ls";
shellStream.WriteLine(cmd + "; echo !");
while (shellStream.Length == 0)
Thread.Sleep(500);

StringBuilder result = new StringBuilder();
string line;

string dbt = @"PuttyTest.txt";
StreamWriter sw = new StreamWriter(dbt, append: true);

while ((line = shellStream.ReadLine()) != "!")
{
result.AppendLine(line);
sw.WriteLine(line);
}

sw.Close();
sshClient.Disconnect();
sshClient.Dispose();
Console.ReadKey();

Providing input/subcommands to a command (cli) executed with SSH.NET SshClient.RunCommand

AFAIK, cli is a kind of a shell/interactive program. So I assume you have tried to do something like:

client.RunCommand("cli");
client.RunCommand("some cli subcommand");

That's wrong. cli will keep waiting for subcommands and never exit, until you explicitly close it with a respective command (like exit). And after it exits, the server will try to execute the cli subcommand as a separate top-level command, failing too.


You have to feed the "cli subcommand" to the input of the cli command. But SSH.NET unfortunately does not support providing an input with the SshClient.RunCommand/SshClient.CreateCommand interface. See Allow writing to SshCommand.


There are two solutions:

  • Use the appropriate syntax of the server's shell to generate the input on the server, like:

    client.RunCommand("echo \"cli subcommand\" | cli");
  • Or use a shell session (what is otherwise a not recommended approach for automating a command execution).

    Use SshClient.CreateShellStream or SshClient.CreateShell and send the commands to its input:

    "cli\n" + "cli subcommand\n"

    For a sample code see Providing subcommands to a command (sudo/su) executed with SSH.NET SshClient.CreateShellStream or C# send Ctrl+Y over SSH.NET.

Command not fully executing under ssh.net in c#

The solution is to use sshclient.CreateShellStream() so that the ssh api doesn't return just because nothing has been returned from execution in shell.

SSH.NET is not executing command on device

Your server obviously does not support the SSH "exec" channel that is used behind the SSH.NET SshClient.RunCommand method and PLink's plink.exe command syntax.

Or actually it does support it, but incorrectly. It seems to start an interactive session (a shell), instead of executing the command.

To confirm this assumption, try this with PLink:

echo AT| plink username@ip -pw password > log.txt

If that works, you may need to use the SshClient.CreateShell (SSH "shell" channel") and write the command to its input stream, instead of using the SshClient.RunCommand. While this is generally a wrong approach, you need to take this approach due to your broken server.


A similar question for Python/Paramiko:

Executing command using Paramiko exec_command on device is not working
.

Executing command using SSH.NET on digi 6030dx modem - what are this character sequences starting with left square bracket?

Those are ANSI escape codes.

In general, with SSH, you get these only if your client (library) declares support for terminal emulation.

SSH.NET library does that always, when you use the "shell" channel (SshClient.CreateShell or SshClient.CreateShellStream).

In general (were you connecting to well behaving SSH server), to avoid getting the codes:

  • Use "exec" channel (use SshClient.RunCommand). SSH.NET does not use terminal emulation on "exec" channel. Though SSH servers on "devices" (contrary to full servers) usually do not implement the "exec" channel. See also What is the difference between exec_command and send with invoke_shell() on Paramiko?

  • Modify SSH.NET code not to request terminal emulation for the "shell" channel. – Remove SendPseudoTerminalRequest request from Shell.Start implementation.


Though as you are connecting to some "device" and telneting further to another device and the codes probably come from the far device, the question is whether this will in fact have any effect on that device at all. Possibly you won't be able to avoid getting the codes. Lack of terminal emulation on the first SSH connection possibly won't have any effect on the second telnet connection.

In the end, you may have to deal with the codes.

See also How to strip ANSI escape codes from AIX topas command result in C#.

Client crashing when running command with Renci SshNet

I'm not quite sure if I get you right, but I would wrap try and catch around the problematic code, especially if you don't care about the output in that case.

private void button1_Click(object sender, EventArgs e)
{
using (var client = new SshClient("IP", "USER", "PASS"))
{

label1.Text = "Status: Initiated restart";
try
{
client.Connect();
var cmd = client.RunCommand("./server restart && ./server2 restart");
var result = cmd.Execute();

client.Disconnect();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}

label1.Text = "Status: Restart completed";
}
}


Related Topics



Leave a reply



Submit