Getting full command output from ShellStream of C# SSH.NET

23,721

The shell is an endless stream. There's no send command – receive output sequence. The ReadToEnd cannot know where an output of one command ends. All you can do is to read until you yourself can tell that the output ended. If you cannot tell that, you can help yourself by appending some kind of end-of-output mark like:

command 1 ; echo this-is-the-end-of-the-output

and read until you get "this-is-the-end-of-the-output" line.


Generally a "shell" channel is not an ideal solution for automation. It's intended for an interactive sessions.

You better use "exec" channel using SshClient.CreateCommand. With CreateCommand the channel closes once the command finishes. So there's clear "end of the stream", what makes the ReadToEnd() work as you expect. And SSH.NET even makes whole command output available in SshCommand.Result (which internally uses ReadToEnd()).

Share:
23,721
T4mer
Author by

T4mer

Updated on July 29, 2022

Comments

  • T4mer
    T4mer over 1 year

    Using Renci.SshNet library. I am trying to execute some commands. After executing "command 1", I am executing "command 2" which takes more time.

    I am only getting the first line of the output. (reader.ReadToEnd() is not working in a proper way).

    I also tried while (!reader.EndOfStream){ } with no luck.

    I think it is because the delay of the response from server. When there is no response the stream read nothing and finishes.

    I found a solution

    String tmp;
    TimeSpan timeout = new TimeSpan(0, 0, 3);
    while ((tmp = s.ReadLine()) != null)
    {
        Console.WriteLine(tmp);
    }
    

    But this is not professional. I need some way in which the stream ends when it ends.

    using (var vclient = new SshClient("host", "username", "password"))
    {
        vclient.Connect();
        using (ShellStream shell = vclient.CreateShellStream("dumb", 80, 24, 800, 600, 1024))
        {
            Console.WriteLine(SendCommand("comand 1", shell));
            Console.WriteLine(SendCommand("comand 2", shell));
            shell.Close();
        }
        vclient.Disconnect();
    }
    
    public static string SendCommand(string cmd, ShellStream sh)
    {
        StreamReader reader = null;
        try
        {
            reader = new StreamReader(sh);
            StreamWriter writer = new StreamWriter(sh);
            writer.AutoFlush = true;
            writer.WriteLine(cmd);
            while (sh.Length == 0)
            {
                Thread.Sleep(500);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("exception: " + ex.ToString());
        }
        return reader.ReadToEnd();
    }