使用Renci SSH.NET执行交换机SSH命令时出现挂起问题求助
解决Renci SSH.NET与以太网交换机交互时的挂起问题
你的问题核心在于多数以太网交换机的SSH shell并非标准POSIX shell:执行命令后,设备不会自动退出会话或发送EOF信号,而是停留在提示符等待下一条命令,导致SSH.NET的RunCommand/Execute方法一直阻塞等待流结束;用StreamReader时也会因为设备未终止输出而无限等待。
Renci SSH.NET本身支持同步命令响应,但需要针对网络设备的特性调整实现方式,以下是可行的解决方案:
1. 使用ShellStream实现交互式命令处理(推荐)
通过模拟交互式SSH会话,以设备的提示符作为命令执行完成的标记,避免无限等待:
using Renci.SshNet; using System.Text; using System.Threading; class SshSwitchExample { static void Main(string[] args) { string ipValue = "你的交换机IP"; string username = "admin"; string password = "admin"; string devicePrompt = "admin>"; // 替换为你的交换机实际提示符 using (var sshClient = new SshClient(ipValue, username, password)) { sshClient.Connect(); // 创建ShellStream,参数分别为终端类型、列数、行数、宽、高、缓冲区大小 using (var shellStream = sshClient.CreateShellStream("xterm", 80, 24, 800, 600, 1024)) { // 先读取初始登录后的提示符 ReadUntilPrompt(shellStream, devicePrompt); // 发送目标命令 shellStream.WriteLine("show ip arp"); // 读取命令输出直到提示符再次出现 string commandOutput = ReadUntilPrompt(shellStream, devicePrompt); // 清理输出:移除命令本身和末尾的提示符 commandOutput = commandOutput.Replace("show ip arp", "") .TrimEnd() .Replace(devicePrompt, "") .Trim(); Console.WriteLine("命令输出:\n" + commandOutput); } sshClient.Disconnect(); } } /// <summary> /// 读取流内容直到出现指定提示符 /// </summary> private static string ReadUntilPrompt(ShellStream shellStream, string prompt) { StringBuilder outputBuilder = new StringBuilder(); while (!outputBuilder.ToString().EndsWith(prompt)) { if (shellStream.DataAvailable) { outputBuilder.Append(shellStream.Read()); } else { Thread.Sleep(100); // 短暂等待,避免CPU空转 } } return outputBuilder.ToString(); } }
2. 给命令添加超时机制(应急方案)
如果不需要完整的交互式处理,可以用Task包装命令执行,设置超时避免永久挂起:
using Renci.SshNet; using System; using System.Threading.Tasks; class SshCommandTimeoutExample { static void Main(string[] args) { string ipValue = "你的交换机IP"; using (var sshClient = new SshClient(ipValue, "admin", "admin")) { sshClient.Connect(); var command = sshClient.CreateCommand("show ip arp"); // 用Task包装命令执行,设置10秒超时 var executeTask = Task.Run(() => command.Execute()); if (executeTask.Wait(TimeSpan.FromSeconds(10))) { Console.WriteLine("命令输出:\n" + command.Result); } else { Console.WriteLine("命令执行超时"); command.CancelAsync(); // 取消阻塞的命令 } sshClient.Disconnect(); } } }
3. 尝试命令串联(仅部分设备支持)
少数支持类POSIX语法的设备,可以在命令后追加exit强制结束会话,但多数交换机不支持这种方式,可尝试:
var command = cSSH.CreateCommand("show ip arp; exit"); command.Execute();
内容的提问来源于stack exchange,提问作者DavidJ
相关产品推荐
相关产品推荐

