C# 使用SSH库连接到unix并跟踪文件:这是正确的方法吗?

C# 使用SSH库连接到unix并跟踪文件:这是正确的方法吗?,c#,multithreading,unix,.net-4.0,ssh,C#,Multithreading,Unix,.net 4.0,Ssh,正如我在其他几个问题中所说的,我一直在使用连接到Unix服务器并运行各种脚本和命令。好的,我终于尝试使用它在一个实时日志文件上运行Unix tail-f,并在Winforms RichTextBox中显示该tail 由于图书馆还没有完全充实起来,我提出的唯一一种解决方案似乎是缺乏的。。。就像你知道必须有更好的方法时的感觉。我将连接/跟踪代码放在一个单独的线程中,以避免UI线程锁定。此线程支持取消请求(这将允许连接正常退出,这是确保进程Unix端被终止的唯一方法)。以下是我迄今为止的代码(记录在案

正如我在其他几个问题中所说的,我一直在使用连接到Unix服务器并运行各种脚本和命令。好的,我终于尝试使用它在一个实时日志文件上运行Unix tail-f,并在Winforms RichTextBox中显示该tail

由于图书馆还没有完全充实起来,我提出的唯一一种解决方案似乎是缺乏的。。。就像你知道必须有更好的方法时的感觉。我将连接/跟踪代码放在一个单独的线程中,以避免UI线程锁定。此线程支持取消请求(这将允许连接正常退出,这是确保进程Unix端被终止的唯一方法)。以下是我迄今为止的代码(记录在案,我只是想了解一下这是否是正确的方法):

UpdateTextBox()函数是一种线程安全的更新RichTextBox的方法,用于显示来自不同线程的尾部。positionLastWrite是为了确保线程之间没有丢失任何数据。Sleep(1000)


现在我不确定有两件事,第一件是我感觉每次都会因为记忆流位置的改变而遗漏一些数据(由于我对MemoryStream缺乏经验,第二个原因是,整个睡眠时间为1秒,然后再次更新的事情似乎非常陈旧和低效……有什么想法吗?

Mh,我刚刚意识到你不是SSH库的创建者(尽管它在codeplex上,所以你可以提交补丁),无论如何:您可能希望将循环包装成一个
尝试{}finally{}
并在finally块中调用
shell.Stop()
,以确保它始终被清理

根据可用接口的不同,轮询可能是唯一的方法,它本身并不坏。是否释放数据取决于
shell
对象在缓冲时做了什么:它是否缓冲内存中的所有输出,是否在一定时间后丢弃一些输出

我最初的观点仍然有效:

我想到的一件事是,
shell
对象似乎一直在内存中缓冲整个输出,这会造成潜在的资源问题(内存不足)。更改接口的一个选项是在shell对象中使用类似a的内容。然后,shell将远程主机的输出排队,您可以坐在那里,然后在客户端中退出队列,如果没有可读取的内容,该队列将被阻止


也:我会考虑制作shell对象(无论是什么类型的代码>创建文件< /COD>返回)<代码> IDISPOSTABLE 。需要清理,如果while循环中出现异常,则不会发生这种情况。

该库有一个自定义内存流,它使用的名为PipeStream,创建者使其听起来就像您描述的阻塞队列,如果有机会,请查看此消息:@Hershizer33,
PipeStream
看起来就是您想要的你想要。虽然
ReadAvailable
的实现似乎有点奇怪:它总是要求缓冲区至少有
count
字节来读取或刷新。使用PipeStream带来了一些问题…似乎在其代码的读取功能中永远循环,但我能想到的唯一原因是,因为日志文件是streaming非常快,它总是有数据要读,并且一直在读……有什么想法吗?尝试不使用
StreamReader
,直接使用流的
read
方法,看看你从中得到了什么。这似乎奏效了,只是担心现在可能会丢失数据……我的循环内部现在看起来是这样的:
byte[]tempBytes=new byte[output.Length];output.Read(tempBytes,0,tempBytes.Length);System.Text.ascienceoding enc=new System.Text.ascienceoding();string result=enc.GetString(tempBytes);updatea2textbox(result);Thread.Sleep(1000);
I图由于这应该删除它读取的内容,所以可以始终从0到1000开始读取
PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo(lineIP, userName, password);

string command = "cd /logs; tail -f " + BuildFileName() + " \r\n";

using (var ssh = new SshClient(connectionInfo))
{
    ssh.Connect();

    var output = new MemoryStream();
    var shell = ssh.CreateShell(Encoding.ASCII, command, output, output);

    shell.Start();

    long positionLastWrite = 0;

    while (!TestBackgroundWorker.CancellationPending) //checks for cancel request  
    {
        output.Position = positionLastWrite;

        var result = new StreamReader(output, Encoding.ASCII).ReadToEnd();
        positionLastWrite = output.Position;
        UpdateTextBox(result);

        Thread.Sleep(1000);
    }

    shell.Stop();
    e.Cancel = true;
}