从C# SSH.NET的ShellStream中获取完整的命令输出

4
使用 Renci.SshNet 库。我正在尝试执行一些命令。在执行 "command 1" 后,我执行需要更多时间的 "command 2"。
我只得到输出的第一行。(reader.ReadToEnd() 没有正常工作)。
我还尝试了 while (!reader.EndOfStream){ },但没有成功。
我认为这是由于服务器响应的延迟造成的。当没有响应时,流不会读取任何内容并结束。
我找到了一个解决方案。
String tmp;
TimeSpan timeout = new TimeSpan(0, 0, 3);
while ((tmp = s.ReadLine()) != null)
{
    Console.WriteLine(tmp);
}

但这不是专业的。我需要一种当流结束时就结束的方法。

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();
}               
1个回答

6

Shell是一个无限流。没有发送命令 - 接收输出序列。 ReadToEnd 不知道一个命令的输出何时结束。你所能做的就是读取,直到你自己能够确定输出已经结束。 如果你无法确定输出是否结束,可以在末尾添加某种输出结束标记来帮助自己,例如:

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

阅读直到您看到"this-is-the-end-of-the-output"行。


一般来说,“shell”通道不是自动化的理想解决方案。它用于交互式会话。

最好使用“exec”通道,使用SshClient.CreateCommand。使用CreateCommand后,通道在命令完成后关闭。因此有明确的“流结束”,这使得ReadToEnd()按您的期望工作。而且SSH.NET甚至可以将整个命令输出可用于SshCommand.Result(内部使用ReadToEnd())。


1
太棒了!正好我一直在寻找一个能告诉我何时完成的东西。响应上的检查和过滤非常容易。 - user1853517

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接