Providing Input/Subcommands to a Command (Cli) Executed with Ssh.Net Sshclient.Runcommand

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.

Providing subcommands to a command (sudo/su) executed with SSH.NET SshClient.CreateShellStream

Just write the "commands" to the StreamWriter.

writer.WriteLine("sudo su - wwabc11");
writer.WriteLine("whoami");
// etc

See also C# send Ctrl+Y over SSH.NET.


Though note that using CreateShellStream ("shell" channel) is not the correct way to automate a commands execution. You should use CreateCommand/RunCommand ("exec" channel). Though SSH.NET limited API to the "exec" channel does not support providing an input to commands executed this way. And whoami and the others are actually inputs to sudo/su command.

A solution would be to provide the commands to su on its command-line, like:

sudo su - wwabc11 -c "whoami ; cd /wwabc11/batch/bin/ ; pwd"

For an example of code that uses CreateCommand to execute a command and reads its output, see see SSH.NET real-time command output monitoring.

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
.

Password change command via SSH using SSH.NET on z/OS

Your server does not seem to support the "shell" channel, only the "exec" channel.

Indeed SSH.NET does not support providing an input to a command executed with the "exec" channel. See Providing input/subcommands to a command (cli) executed with SSH.NET SshClient.RunCommand

Were it a *nix server, you might try to provide the input using input redirection.

client.RunCommand("echo input | command");

Though 1) this is not a safe way for passwords 2) I do not know a proper syntax for z/OS (or if it is even possible).


To allow providing the input properly, you would have to grab SSH.NET code and modify the SshCommand class to expose IChannelSession.Write the way ShellStream.Write does.


Or you will have to use a different library (I do not know other free good one than SSH.NET though). Or run an external tool like PuTTY Plink (I do not like that, but it's probably easiest way to go). See Sending input during command output with SSH.NET.

C# send Ctrl+Y over SSH.NET

SSH.NET does not support sending an input to commands executed with SshClient.RunCommand ("exec" channel).

You have to use a "shell" channel (SshClient.CreateShell or SshClient.CreateShellStream). This is normally not recommended for a command automation. Even more so with SSH.NET, which does not even allow your to turn off a pseudo terminal for the "shell" channel. This brings lots of nasty side effects, particularly with "smart" shells on Linux. But with devices likes switches, it might be bearable.

Also particularly sending control sequences like Ctrl+Y is more complicated with the pseudo terminal. But again, let's hope that the "shell" of the switch is dumb enough to simply accept a pure ASCII cide for Ctrl+Y, what is 25 = x19.

ShellStream shellStream = client.CreateShellStream(string.Empty, 0, 0, 0, 0, 0);
shellStream.Write("enable\n");
shellStream.Write("\u19");

while (true)
{
string s = shellStream.Read();
Console.Write(s);
}

SSH and sudo connection to MySQL instance from C#

I just wanted to update this thread with the solution that worked for me. I ended up using a mysql connector as suggested above.

using MySql.Data;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;

namespace DBconnector
{
class DBConnect
{
public MySqlConnection connection;
private string server;
private string database;
private string uid;
private string password;

//Constructor
public DBConnect()
{
Initialize();
}

private void Initialize()
{
Console.WriteLine("Initializing Connection...");
server = "192.168.0.60";
database = "devDB";
uid = "user";
password = "password";
string connectionString;
connectionString = "SERVER="+server+";" + "UID="+uid+";" + "DATABASE="+database+";" + "PASSWORD="+password+";";

connection = new MySqlConnection(connectionString);
}

/* Sample select statement from a table in the DB */
public List<string> SelectFBOEntries(String statement)
{
string query = statement;
List<string> response = new List<string>();
if (this.OpenConnection())
{
MySqlCommand cmd = new MySqlCommand(query, connection);
MySqlDataReader dataReader = cmd.ExecuteReader();

//Read the data and store them in the list
while (dataReader.Read())
{
response.Add(dataReader["ID"] + "");
response.Add(dataReader["Name"] + "");
response.Add(dataReader["Age"] + "");
response.Add(dataReader["DOB"] + "");
response.Add(dataReader["ZIP"] + "");
}
dataReader.Close();
this.CloseConnection();
return response;
}
else
{
return response;
}
}

public bool CloseConnection()
{
try
{
connection.Close();
return true;
}
catch (MySqlException ex)
{
Console.WriteLine("Error Closing Connection");
return false;
}
}

Execute (sub)commands in secondary shell/command on SSH server in Python Paramiko

I assume that the gotoshell and hapi_debug=1 are not top-level commands, but subcommands of the stcli. In other words, the stcli is kind of a shell.

In that case, you need to write the commands that you want to execute in the subshell to its stdin:

stdin, stdout, stderr = ssh.exec_command('stcli')
stdin.write('gotoshell\n')
stdin.write('hapi_debug=1\n')
stdin.flush()

If you call stdout.read afterwards, it will wait until the command stcli finishes. What it never does. If you wanted to keep reading the output, you need to send a command that terminates the subshell (typically exit\n).

stdin.write('exit\n')
stdin.flush()
print(stdout.read())


Related Topics



Leave a reply



Submit