如何写入stdin /从SSH连接的远程进程的stdout读取? (Renci.SshNet)

我想连接一个SSH服务器,在连接时,它运行一个自定义命令,它需要XML作为输入(UTF-8编码,多行,每行XML文档末尾有一个特殊行标记它的结尾)并输出XML( UTF-8编码,多行,末尾有相同的特殊行,表示文档结尾)。

目前有一种使用plink.exe(PuTTy成名)的机制(意思是:服务器端确实按指定的方式工作),但我正在消除对外部进程的需求。

我正在试图Renci.SshNet库,但我发现文档不合适,找不到我需要的例子。

我到目前为止的尝试:

using System; using Renci.SshNet; namespace ServerConnect { public class ServerConnection { private const string EOC= "*-* COMMAND DELIMITER *-*"; private SshClient scon; private System.IO.Stream stdin, stdout, stderr; private System.IO.StreamWriter stdin_writer; private System.IO.StreamReader stdout_reader; private Shell shell; public ServerConnection (string keyFileName, string keyFilePassphrase) { ConnectionInfo ci= new ConnectionInfo("my.server.local", 22, "datamgr", new PrivateKeyAuthenticationMethod("datamgr", new PrivateKeyFile(keyFileName, keyFilePassphrase))); this.scon= new SshClient(ci); } public ServerConnection (string keyFilePassphrase): this("client_id_rsa", keyFilePassphrase) {} public void Connect() { this.scon.Connect(); this.stdin= new System.IO.MemoryStream(); this.stdin_writer= new System.IO.StreamWriter(stdin); this.stdout= new System.IO.MemoryStream(); this.stdout_reader= new System.IO.StreamReader(stdout); this.stderr= new System.IO.MemoryStream(); this.shell= this.scon.CreateShell(this.stdin, this.stdout, this.stderr); this.shell.Start(); } public void Disconnect() { this.scon.Disconnect(); } public string Command(string text) { Console.WriteLine("sending command"); this.stdin_writer.WriteLine(text); Console.WriteLine("sending EOC"); this.stdin_writer.WriteLine(EOC); this.stdin_writer.Flush(); for (;;) { string line; line= this.stdout_reader.ReadLine(); if (line == null) { Console.WriteLine("got null"); break; } Console.WriteLine("READ"); Console.WriteLine(line); if (line.StartsWith(EOC)) break; } return ""; // yes, this should return the built output } } } 

鉴于这是一个程序集,我正处于尝试连接到服务器的阶段(测试通过booish轻松实现):

 >>> import ServerConnect >>> a= ServerConnection("passphrase") ServerConnect.ServerConnection >>> a.Connect() >>> a.Command("") sending command sending EOC got null '' 

我可以看到(在服务器的auth.log中)在a.Connect()调用之后建立连接。 但是,似乎我写给stdin_writer任何stdin_writer都没有被发送到服务器。

我怎样才能完成这个机制? 将数据发送到服务器,然后发送分隔符,然后读取数据,直到我读取分隔符? 在连接期间,该循环将重复多次。

请注意,我不是一名经验丰富的C#程序员,因此我可能对C#流模型缺乏基本的了解。

PS我已经看到了这个答案,但似乎CreateShellStream调用块,可能是在PseudoTty分配中(该过程不需要伪ttys,只需要输入/输出)。

PS2我从codeplex.com下载并编译了最新版本的Renci.SshNet,现在我就在这一点上(摘自Connect方法):

 this.scon.Connect(); this.stream= this.scon.CreateShellStream("dumb", 80, 24, 800, 600, 1024); this.stdin_writer= new System.IO.StreamWriter(this.stream); this.stdout_reader= new System.IO.StreamReader(this.stream); this.shell= this.scon.CreateShell(this.stream, this.stream, this.stream); this.shell.Start(); 

但是,对stdin_writer(随后的刷新)的任何写入似乎都没有通过。

对不起,输入后我注意到我发了necro …

您可以使用此处给出的解决方案,这是我在想要做与您类似的事情时使用的解决方案:

Renci ssh.net – 连接时从表单创建控制台屏幕

您可以使用任何System.IO对象,并使用ShellStream对象操作SSH会话IO。

ShellStream.Expect将读取输出,并查找特定的字符串。 ShellStream.WriteLine将向shell发送输入。

  string reply = string.Empty; ShellStream ss = scon.CreateShellStream("dumb", 80, 24, 800, 600, 1024); reply = ss.Expect("Press enter to continue"); //The prompt I get after login ParseOutput(reply); ss.WriteLine("./myscript.sh") reply = ss.Expect("$"); //My prompt, when the script has finished. ParseOutput(reply); 

ParseOutput是我写的一个例程,用于在每个换行符处拆分“回复”字符串,并将每一行添加到表单上的列表框中。

Renci.SshNet(尚未)这是不可能的。

第一个响应没有解决将数据传输到远程执行的命令的标准输入的原始问题。 典型的示例是将压缩文件的内容流式传输到解压缩器以在目标主机上执行。

直到最近(2016年9月11日)才为GitHub中的SSH.NET项目提出了这一增强function。 你可以在这里看到它:

支持在执行远程命令时写入stdin