Pix*_*xar 3 wpf ssh monitoring async-await ssh.net
script.sh
远程Linux机器上有一个运行时间很长的脚本.我需要启动它并实时监控它的活动.它活动期间的脚本可以输出到stdout
和stderr
.我正在寻找一种捕获两种流的方法.
我使用Renci SSH.NET上传script.sh
并启动它,所以很高兴看到这个库有一个解决方案.在我看来,完美的解决方案是新方法:
var realTimeScreen= ...;
var commandExecutionStatus = sshClient.RunCommandAsync(
command: './script.sh',
stdoutEventHandler: stdoutString => realTimeScreen.UpdateStdout(stdString)
stderrEventHandler: stderrString => realTimeScreen.UpdateStderr(stderrString));
...
commandExecutionStatus.ContinueWith(monitoringTask =>
{
if (monitoringTask.Completed)
{
realTimeScreen.Finish();
}
});
Run Code Online (Sandbox Code Playgroud)
Mar*_*ryl 11
使用SshClient.CreateCommand
方法.它返回SshCommand
实例.
本SshCommand
类具有ExtendedOutputStream
属性,返回与两个输出和错误流.
见SshCommandTest.cs
:
public void Test_Execute_ExtendedOutputStream()
{
var host = Resources.HOST;
var username = Resources.USERNAME;
var password = Resources.PASSWORD;
using (var client = new SshClient(host, username, password))
{
#region Example SshCommand CreateCommand Execute ExtendedOutputStream
client.Connect();
var cmd = client.CreateCommand("echo 12345; echo 654321 >&2");
var result = cmd.Execute();
Console.Write(result);
var reader = new StreamReader(cmd.ExtendedOutputStream);
Console.WriteLine("DEBUG:");
Console.Write(reader.ReadToEnd());
client.Disconnect();
#endregion
Assert.Inconclusive();
}
}
Run Code Online (Sandbox Code Playgroud)
另请参阅类似WinForms问题的完整代码在SSH.NET中执行长时间命令并在TextBox中连续显示结果.
所以,这是我提出的解决方案.当然,它可以改进,所以批评是开放的.
我用了
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
Run Code Online (Sandbox Code Playgroud)
而不是Task.Yield()
因为Task.Yield()
将继续比GUI事件更高的优先级,但是,作为一个坏的结果,它要求您的应用程序使用WindowsBase.dll
.
public static class SshCommandExtensions
{
public static async Task ExecuteAsync(
this SshCommand sshCommand,
IProgress<ScriptOutputLine> progress,
CancellationToken cancellationToken)
{
var asyncResult = sshCommand.BeginExecute();
var stdoutStreamReader = new StreamReader(sshCommand.OutputStream);
var stderrStreamReader = new StreamReader(sshCommand.ExtendedOutputStream);
while (!asyncResult.IsCompleted)
{
await CheckOutputAndReportProgress(
sshCommand,
stdoutStreamReader,
stderrStreamReader,
progress,
cancellationToken);
await Dispatcher.Yield(DispatcherPriority.ApplicationIdle);
}
sshCommand.EndExecute(asyncResult);
await CheckOutputAndReportProgress(
sshCommand,
stdoutStreamReader,
stderrStreamReader,
progress,
cancellationToken);
}
private static async Task CheckOutputAndReportProgress(
SshCommand sshCommand,
TextReader stdoutStreamReader,
TextReader stderrStreamReader,
IProgress<ScriptOutputLine> progress,
CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
sshCommand.CancelAsync();
}
cancellationToken.ThrowIfCancellationRequested();
await CheckStdoutAndReportProgressAsync(stdoutStreamReader, progress);
await CheckStderrAndReportProgressAsync(stderrStreamReader, progress);
}
private static async Task CheckStdoutAndReportProgressAsync(
TextReader stdoutStreamReader,
IProgress<ScriptOutputLine> stdoutProgress)
{
var stdoutLine = await stdoutStreamReader.ReadToEndAsync();
if (!string.IsNullOrEmpty(stdoutLine))
{
stdoutProgress.Report(new ScriptOutputLine(
line: stdoutLine,
isErrorLine: false));
}
}
private static async Task CheckStderrAndReportProgressAsync(
TextReader stderrStreamReader,
IProgress<ScriptOutputLine> stderrProgress)
{
var stderrLine = await stderrStreamReader.ReadToEndAsync();
if (!string.IsNullOrEmpty(stderrLine))
{
stderrProgress.Report(new ScriptOutputLine(
line: stderrLine,
isErrorLine: true));
}
}
}
public class ScriptOutputLine
{
public ScriptOutputLine(string line, bool isErrorLine)
{
Line = line;
IsErrorLine = isErrorLine;
}
public string Line { get; private set; }
public bool IsErrorLine { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16466 次 |
最近记录: |