在 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;
}
}
我正在做一个家庭项目,需要通过 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;
}
}