gpt4 book ai didi

c# - 如何写入标准输入/从 SSH 连接的远程进程的标准输出读取? (Renci.SshNet)

转载 作者:行者123 更新时间:2023-11-30 12:26:00 25 4
gpt4 key购买 nike

我想连接一个 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("<i command=\"ping\"/>")
sending command
sending EOC
got null
''

我可以看到(在服务器的 auth.log 中)连接是在 a.Connect() 调用之后建立的。但是,似乎无论我写入 stdin_writer 都不会发送到服务器。

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

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

PS 我看过this答案,但似乎 CreateShellStream 调用 block ,可能在 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 的任何写入(以及随后的刷新)似乎都没有通过。

最佳答案

抱歉,输入此内容后我发现我在发帖...

你可以使用这里给出的解决方案,这是我想做类似你的事情时使用的:

Renci ssh.net - Create console screen from form when connected

您可以放弃使用任何 System.IO 对象并使用 ShellStream 对象操纵 SSH session 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 是我编写的一个例程,用于在每个换行符处拆分“回复”字符串,并将每一行添加到表单的列表框中。

关于c# - 如何写入标准输入/从 SSH 连接的远程进程的标准输出读取? (Renci.SshNet),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30079526/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com