使用SSH.NET遇伪终端错误,如何实现PuTTY远程命令功能?
使用SSH.NET实现PuTTY风格的SSH代理跳转会话
问题根源
你之前的代码错误在于直接执行CreateCommand("user@server1")——这不是合法的Shell命令。PuTTY在"Remote command"中输入user@server1时,实际是触发交互式SSH登录到目标机器;而SSH.NET的CreateCommand默认执行非交互式命令,不会分配伪终端,因此出现"Pseudo-terminal will not be allocated"报错;同时错误的命令触发了无效认证流程,导致多次认证失败被服务器断开。
解决方案
方案1:交互式会话(模拟PuTTY终端,支持输入目标机器密码)
通过CreateShellStream创建带伪终端的会话,模拟PuTTY的终端环境,触发交互式SSH登录并处理密码输入:
var pk = new PrivateKeyFile("C:\\xxx.ppk"); var client = new SshClient("代理服务器IP", "代理服务器登录名", pk); client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(10); client.Connect(); // 创建带伪终端的Shell流,匹配PuTTY的终端环境配置 var shellStream = client.CreateShellStream("vt100", 250, 250, 800, 160, 512); // 发送SSH登录目标机器的命令,和PuTTY Remote command效果一致 shellStream.WriteLine("ssh user@server1"); // 读取输出,等待目标机器的密码提示 string output = string.Empty; while (!output.Contains("password:")) { output += shellStream.Read(); Thread.Sleep(100); } // 输入目标机器密码(必须加换行符触发提交) shellStream.WriteLine("目标机器登录密码"); // 读取登录后的输出,或继续发送后续命令 string response = shellStream.Read(); Console.WriteLine(response); // 结束操作时断开连接 // client.Disconnect();
方案2:免密密钥登录目标机器(无需交互输入)
如果已将代理服务器的公钥添加到目标机器的~/.ssh/authorized_keys中,可直接执行带强制终端参数的SSH命令:
var pk = new PrivateKeyFile("C:\\xxx.ppk"); var client = new SshClient("代理服务器IP", "代理服务器登录名", pk); client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(10); client.Connect(); // 使用-t参数强制分配伪终端,解决非交互式命令的终端报错 var command = client.CreateCommand("ssh -t user@server1"); var response = command.Execute(); Console.WriteLine(response); // 结束操作时断开连接 // client.Disconnect();
关键说明
-t参数:强制SSH分配伪终端,解决"Pseudo-terminal will not be allocated"的核心问题- 交互式会话的本质:PuTTY的"Remote command"并非直接执行命令,而是在终端环境中触发SSH跳转,因此必须用
ShellStream模拟终端交互才能匹配其行为
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

