You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:23:23