ssh.net c# runcommand issue - c#

I am using Renci.SshNet in c# on framework 3.5 and running a command on unix box like below.
string host = "localhost";
string user = "user";
string pass = "1234";
SshClient ssh = new SshClient(host, user, pass);
using (var client = new SshClient(host, user, pass))
{
client.Connect();
var terminal = client.RunCommand("/bin/run.sh");
var output = terminal.Result;
txtResult.Text = output;
client.Disconnect();
}
every thing works well, my question here is that "Is there a way that it should not wait for client.RunCommand to be finish" My prog doesn't need a output from unix and hence I don't want to wait for the RunCommand to finish. This command took 2 hours to execute so wanted to avoid that wait time on my application.

As i assume SSH.NET doesn't expose a true asynchronous api, you can queue RunCommand on the threadpool:
public void ExecuteCommandOnThreadPool()
{
string host = "localhost";
string user = "user";
string pass = "1234";
Action runCommand = () =>
{
SshClient client = new SshClient(host, user, pass);
try
{
client.Connect();
var terminal = client.RunCommand("/bin/run.sh");
txtResult.Text = terminal.Result;
}
finally
{
client.Disconnect();
client.Dispose();
}
};
ThreadPool.QueueUserWorkItem(x => runCommand());
}
}
Note if you use this inside WPF or WinForms then you will need to txtResult.Text = terminal.Result with Dispatcher.Invoke or Control.Invoke, respectively.

What about
public static string Command(string command)
{
var cmd = CurrentTunnel.CreateCommand(command); // very long list
var asynch = cmd.BeginExecute(
//delegate { if (Core.IsDeveloper) Console.WriteLine("Command executed: {0}", command); }, null
);
cmd.EndExecute(asynch);
if (cmd.Error.HasValue())
{
switch (cmd.Error) {
//case "warning: screen width 0 suboptimal.\n" => add "export COLUMNS=300;" to command
default: MessageBox.Show(cmd.Error); break;
}
}
return cmd.Result;
}

Related

Getting SSH output into StreamReader from long running SSH commands

I’m attempting to capture output from a long running SSH command that may take a few seconds to initially produce any text output once called and may take up to a minute to fully complete.
The below code snippet works fine if I issue a simple command to execute such as ls that produces immediate output into the output stream.
However, I get nothing returned and SSH disconnects if I run a command that doesn’t instantly produce any output.
using (var sshClient = new SshClient(target, 22, userName, password))
{
sshClient.Connect();
var cmd = sshClient.CreateCommand(command);
var result = cmd.BeginExecute();
using (var reader = new StreamReader(cmd.OutputStream))
{
while (!reader.EndOfStream || !result.IsCompleted)
{
string line = reader.ReadLine();
if (line != null)
{
Console.WriteLine(line);
}
}
sshClient.Disconnect();
}
}
BeginExecute begins an asynchronous command execution. You need to wait and keep reading the output stream until it completes.
In a simple way,
using (var sshClient = new SshClient(host, 22, username, password)) {
sshClient.Connect();
var cmd = sshClient.CreateCommand("for i in `seq 1 10`; do sleep 1; echo $i; done");
var asyncResult = cmd.BeginExecute();
var outputReader = new StreamReader(cmd.OutputStream);
string output;
while (!asyncResult.IsCompleted) {
output = outputReader.ReadToEnd();
Console.Out.Write(output);
}
output = outputReader.ReadToEnd();
Console.Out.Write(output);
}

StreamSocket crash on Windows 8.1 store app

I have a server-client connection which works on both sides with Windows.Networking.Sockets.StreamSocket. On Windows 10, as Universal App, the connection is successful and data flows in back and forth without problems. On Windows 8.1, as a Windows Store app, the reading part of the StreamSocket fails at first attempt to read incoming data. The app closes and VS 2015 do not report any Exception nor the Output Window contains any useful information, other than Program has exited with code 1. Also, putting a breakpoint and then stepping through code doesn't work. Locals are not displayed and VS shows a message dialog:
Unable to start debugging. The object invoked has disconnected from its clients.
Here is the reading code:
public IAsyncAction Read()
{
return Task.Run(() =>
{
try
{
const uint length = 65536;
string request = string.Empty;
var socket = _signalingSocketService.GetSocket();
var readBuf = new Windows.Storage.Streams.Buffer(length);
var readOp = socket.InputStream.ReadAsync(readBuf, length, InputStreamOptions.Partial);
readOp.Completed = (IAsyncOperationWithProgress<IBuffer, uint> asyncAction, AsyncStatus asyncStatus) =>
{
if(asyncStatus == AsyncStatus.Completed)
{
var localBuffer = asyncAction.GetResults();
var dataReader = DataReader.FromBuffer(localBuffer);
request = dataReader.ReadString(dataReader.UnconsumedBufferLength);
_signalingSocketService.HandoffSocket(socket);
List<string> requests;
var fileTask = BufferFileExists().AsTask();
fileTask.Wait();
if (fileTask.Result)
{
var bufferFileTask = GetBufferFile().AsTask();
bufferFileTask.Wait();
var bufferFile = bufferFileTask.Result;
var task = FileIO.AppendTextAsync(bufferFile, request).AsTask();
task.Wait();
var readLinesTask = FileIO.ReadLinesAsync(bufferFile).AsTask();
readLinesTask.Wait();
requests = (readLinesTask.Result).ToList();
var deleteTask = bufferFile.DeleteAsync().AsTask();
deleteTask.Wait();
}
else
{
requests =
request.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
} // if (asyncStatus == AsyncStatus.Completed)
}; // readOp.Completed
}
catch (Exception ex)
{
}
}
}
What can cause such an odd behavior?

SSH terminal in a webapp using ASP.NET

Hello I creating a webapp that has a working SSH terminal similar to Putty. I'm using SSH Library as a means of handling the ssh stream. However there is a problem. I can log into a Cisco 2950 and type in commands but it comes out jumbled and in one line.
Also when I try "conf t" it gets into the configuration terminal but then you can't do anything and this pops up "Line has invalid autocommand "?".
Here is the code I have so far:
This is the SSH.cs that interacts with the library.
public class SSH
{
public string cmdInput { get; set; }
public string SSHConnect()
{
var PasswordConnection = new PasswordAuthenticationMethod("username", "password");
var KeyboardInteractive = new KeyboardInteractiveAuthenticationMethod("username");
// jmccarthy is the username
var connectionInfo = new ConnectionInfo("10.56.1.2", 22, "username", PasswordConnection, KeyboardInteractive);
var ssh = new SshClient(connectionInfo);
ssh.Connect();
var cmd = ssh.CreateCommand(cmdInput);
var asynch = cmd.BeginExecute(delegate(IAsyncResult ar)
{
//Console.WriteLine("Finished.");
}, null);
var reader = new StreamReader(cmd.OutputStream);
var myData = "";
while (!asynch.IsCompleted)
{
var result = reader.ReadToEnd();
if (string.IsNullOrEmpty(result))
continue;
myData = result;
}
cmd.EndExecute(asynch);
return myData;
}
}
This the code in the .aspx.cs that displays the code on the web page.
protected void CMD(object sender, EventArgs e)
{
SSH s = new SSH();
s.cmdInput = input.Text;
output.Text = s.SSHConnect();
}
Any help would be appreciated.
From looking through the test cases in the code for the SSH.NET library, you can use the RunCommand method instead of CreateCommand, which will synchronously process the command. I also added a using block for the SshClient ssh object since it implements iDisposable. Remember to call Disconnect as well so you don't get stuck with open connections.
Also the SshCommand.Result property (used in the command.Result call below), encapsulates the logic to pull the results from the OutputSteam, and uses this._session.ConnectionInfo.Encoding to read the OutputStream using the proper encoding. This should help with the jumbled lines you were receiving.
Here is an example:
public string SSHConnect() {
var PasswordConnection = new PasswordAuthenticationMethod("username", "password");
var KeyboardInteractive = new KeyboardInteractiveAuthenticationMethod("username");
string myData = null;
var connectionInfo = new ConnectionInfo("10.56.1.2", 22, "username", PasswordConnection, KeyboardInteractive);
using (SshClient ssh = new SshClient(connectionInfo)){
ssh.Connect();
var command = ssh.RunCommand(cmdInput);
myData = command.Result;
ssh.Disconnect();
}
return myData;
}

Connecting to HDInsight Emulator

I am trying to connect with c#.
Here is the class that submits hive queries successfully to my remote HDInsight cluster. what do i need to change here to connect to the local emulator
public class HadoopImporter : IImporter
{
public static readonly Logger log = LogManager.GetCurrentClassLogger();
public void Import(string _query)
{
try
{
log.Warn("Inside Hive submission method");
var store = new X509Store();
store.Open(OpenFlags.ReadOnly);
var cert =
store.Certificates.Cast<X509Certificate2>()
.First(item => item.Thumbprint == "MYCERTTUMBPRINT");
if (cert == null)
log.Error("no cert found");
log.Warn(cert.FriendlyName);
log.Warn("got the cert with thumbprint ", cert.Thumbprint.ToString())
;
log.Warn("trying to create credentials from cert");
var creds = new JobSubmissionCertificateCredential(new Guid("MYSUBSCRIPTIONID"),
cert, "MYSTORAGECONTAINER");
log.Warn("trying to connect with cert");
var jobClient = JobSubmissionClientFactory.Connect(creds);
log.Warn("Setting Hive job parameters");
var hiveJob = new HiveJobCreateParameters()
{
Query = _query,
StatusFolder = "/samplequeryoutput"
};
var jobResults = jobClient.CreateHiveJob(hiveJob);
log.Warn("Executing wait for jhive results");
WaitForJobCompletion(jobResults, jobClient);
using (var stream = jobClient.GetJobOutput(jobResults.JobId))
{
var reader = new StreamReader(stream);
var res = reader.ReadToEnd();
log.Warn("trying to get the job results " + res.ToString());
}
}
catch (Exception exp)
{
log.Error(exp);
}
}
private static void WaitForJobCompletion(JobCreationResults jobDetails, IJobSubmissionClient client)
{
var jobInProgress = client.GetJob(jobDetails.JobId);
while (jobInProgress.StatusCode != JobStatusCode.Completed && jobInProgress.StatusCode != JobStatusCode.Failed)
{
log.Warn("Inside the while loop waiting for hive job to complete");
jobInProgress = client.GetJob(jobInProgress.JobId);
Thread.Sleep(TimeSpan.FromSeconds(10));
}
log.Trace("HIVE Job has Imported " + jobDetails.JobId);
}
}
You should be able to connect to a local one-box using the REST implementation of the client.
You're looking for the WebHCatHttpClient interface. The code below runs a basic query against my local one-box.
var httpClient = new WebHCatHttpClient(new Uri("http://localhost:50111/"), "username", "password");
string outputDir = "basichivejob";
var task = httpClient.CreateHiveJob(#"select * from iris;", null, null, outputDir, null);
task.Wait();
var response = task.Result;
var output = response.Content.ReadAsAsync<JObject>();
output.Wait();
response.EnsureSuccessStatusCode();
string id = output.Result.GetValue("id").ToString();
httpClient.WaitForJobToCompleteAsync(id).Wait();
See the SDK docs for more info.

SSH.NET RunCommand To Save Command Output to File

I'm trying to run a command on a remote server via SSH.
I need the output of the command that is run to be saved in a file on that remote server.
I've been attempting to this the following way
// ssh is the SshClient which is already set up
ssh.Connect();
ssh.RunCommand("echo 1 > C:\test.csv"); //Doesn't create a file
ssh.Disconnect();
Why doesn't this work with SSH.NET? If I run this via putty using the same credentials it works perfectly fine.
EDIT (Working Code):
I did some more playing around and have found the following to work:
// ssh is the SshClient which is already set up
ssh.Connect();
var shell = ssh.CreateShellStream("cmd.exe", 80, 24, 800, 600, 1024);
var reader = new StreamReader(shell);
var writer = new StreamWriter(shell);
writer.AutoFlush = true;
while (!shell.DataAvailable)
System.Threading.Thread.Sleep(1000); //This wait period seems required
writer.WriteLine("echo 1 > C:\test.csv");
while (!shell.DataAvailable)
System.Threading.Thread.Sleep(1000); //This wait period seems required
ssh.Disconnect();
While that works I still don't understand what's really happening here. Could someone explain?
Try this function:
Just save the result to a variable or write the result using StreamWriter
private void writeMe()
{
using (StreamWriter sw = new StreamWriter(filename)
{
string result = eSshCom(command);
sw.WriteLine(result);
}
}
private string eSshCom(string getCommand)
{
this.res = "";
var connectionInfo = new KeyboardInteractiveConnectionInfo(ipaddress, 22, username);
connectionInfo.AuthenticationPrompt += delegate(object asender, AuthenticationPromptEventArgs xe)
{
foreach (var prompt in xe.Prompts)
{
if (prompt.Request.Equals("Password: ", StringComparison.InvariantCultureIgnoreCase))
{
prompt.Response = password;
}
}
};
using (var ssh = new SshClient(connectionInfo))
{
ssh.Connect();
var cmd = ssh.RunCommand(getCommand);
this.res = cmd.Result;
ssh.Disconnect();
}
return this.res;
}

Categories