在 SSH.NET 中逐行读取和处理命令输出

Reading and processing command output line by line in SSH.NET

我正在做一个家庭项目,需要通过 SSH 执行一些命令,读回响应并将它们显示在网页上。很多时候它确实有效,但有时我会遇到一些不一致的行为,例如,错过了指示下一步该做什么的某些输出行,这会导致会话挂起,并要求恢复 IIS。

我已经包含了下面的代码,就像我说的我不是全职开发人员,所以它会一团糟,但希望有人能给我指明正确的方向,以了解我错在哪里,以及什么我需要改变,如果你只是过去的代码片段,我不会学习,我更愿意尝试修复我拥有的东西。

using (SshClient ssh = new SshClient("192.168.0.119", "x", "x."))
{
    ssh.Connect();
    ShellStream shell = ssh.CreateShellStream("Tail", 0, 0, 0, 0, 1024);
    StreamWriter wr = new StreamWriter(shell);
    StreamReader rd = new StreamReader(shell);
    wr.AutoFlush = true;
    if (extract)
    {
        Console.WriteLine("Downloading DataZIP");
        ssh.RunCommand("wget " + zipURL);
    }

    bool reading = shell.CanRead;
    wr.WriteLine("cd " + remoteFilePath + packagename + " && docker build -t dockerfile .");

    while (reading)
    {
        Clients.Caller.builderOut(shell.ReadLine().ToString());
        if (shell.ReadLine().ToString().Contains("Successfully"))
        {
            Clients.Caller.builderOut("Build Complete");
            reading = false;
        }
        if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
        {
            goto end;
        }
    }

    if (data.Type == TemplateType.Data)
    {
        wr.WriteLine("cd " + remoteFilePath + packagename + " && docker tag dockerfile " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
        wr.WriteLine("cd " + remoteFilePath + packagename + " && docker push " + data.Repository + "/" + data.packagename.ToLower() + ":data.Type");
    }

    reading = shell.CanRead;
    while (reading)
    {
        Clients.Caller.builderOut("Pushing this will take a moment");
        if (shell.ReadLine().ToString().Contains("digest:"))
        {
            Clients.Caller.builderOut("Pushed");
            reading = false;
        }
    }

    Clients.Caller.builderOut("End");
    ssh.Disconnect();
    ssh.Dispose();
}

我认为我错了
我想我得到这些错误是因为我读取控制台输出的方式。我认为数据变化如此之快我们错过了一些:

while (reading)
{
    Clients.Caller.builderOut(shell.ReadLine().ToString());
    if (shell.ReadLine().ToString().Contains("Successfully"))
    {
        Clients.Caller.builderOut("Build Complete");
        reading = false;
    }
    if (shell.ReadLine().ToString().Contains("returned a non-zero code: "))
    {
        goto end;
    }
}

因此,我认为对输出使用 3 次检查中的每一次都会丢失一些行,因为输出速度非常快,而它读取的值会发生变化,因此下一次检查有不同的初始数据要检查,因此我们跳过了退出线或下一个工作线。

您必须将读取的行存储到一个变量中,并对存储的值进行检查:

while (reading)
{
    string line = shell.ReadLine();
    Clients.Caller.builderOut(line);
    if (line.Contains("Successfully"))
    {
        Clients.Caller.builderOut("Build Complete");
        reading = false;
    }
    if (line.Contains("returned a non-zero code: "))
    {
        goto end;
    }
}