Использование библиотеки SSH для подключения к unix и создания файла: это правильный подход? - PullRequest
0 голосов
/ 30 июня 2011

Как я уже говорил с несколькими другими вопросами, я использовал новую библиотеку SSH .NET для подключения к серверу Unix и запуска различных сценариев и команд.Что ж, я наконец-то попытался использовать его для запуска хвоста Unix -f в реальном файле журнала и отображения хвоста в Winforms RichTextBox.

Поскольку библиотека не полностью реализована, единственноерешение, которое я придумаю, кажется, не хватает ... как чувство, которое ты испытываешь, когда знаешь, что должен быть лучший путь.У меня есть код подключения / хвоста в отдельном потоке, чтобы избежать блокировок потока пользовательского интерфейса.Этот поток поддерживает запрос отмены (который позволит корректно завершить соединение, единственный способ убедиться, что сторона процесса Unix уничтожена).Ниже приведен мой код (который, похоже, работает для этой записи, хотелось бы подумать, если это правильный путь):

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;
}

Функция UpdateTextBox () является потоком-безопасный способ обновления RichTextBox, используемый для отображения хвоста из другого потока.Материал positionLastWrite - это попытка убедиться, что я не потеряю данные между Thread.Sleep (1000).

Теперь я не уверен насчет двух вещей, во-первых, у меня такое ощущение, что я могу упускать некоторые данные каждый раз из-за меняющейся позиции в MemoryStream (из-за моего отсутствия опыта работы с MemoryStreams иво-вторых, весь сон в течение 1 секунды, а затем обновление снова кажется довольно архаичным и неэффективным ... есть мысли?

1 Ответ

1 голос
/ 30 июня 2011

Мм, я только что понял, что вы не являетесь создателем библиотеки SSH (хотя она находится в codeplex, чтобы вы могли отправлять патчи), в любом случае: вы можете захотеть заключить ваш цикл в try {} finally {} и вызвать shell.Stop() вблок finally, чтобы убедиться, что он всегда очищен.

В зависимости от доступных интерфейсов опрос может быть единственным способом, и он не является плохим по своей сути.Независимо от того, теряете ли вы данные или нет, зависит от того, что объект shell делает для буферизации: буферизует ли он весь вывод в памяти, отбрасывает ли какой-то вывод через определенное время?

Мои исходные точки все еще остаются:

Одна вещь, которая приходит в голову, это то, что похоже, что объект shell постоянно буферизирует весь вывод в памяти, что создает потенциальную проблему с ресурсами.(недостаточно памяти).Один из вариантов изменения интерфейса - использовать что-то вроде BlockingQueue в объекте оболочки.Затем оболочка ставит в очередь выходные данные с удаленного хоста, и в вашем клиенте вы можете просто сидеть там и снимать очередь, которая будет блокироваться, если там нечего читать.

Также: я бы рассмотрел создание объекта оболочки (любой тип CreateShell возвращает) IDisposable.Из вашего описания звучит shell.Stop() требуется для очистки, что не произойдет, если в цикле while будет какое-то исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...