鱼C论坛

 找回密码
 立即注册
查看: 74|回复: 2

C# SSH如何回复确认信息 YES/NO

[复制链接]
发表于 2025-8-13 09:55:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我用C# Renci.SshNet通过SSH协议与Linux系统通信,已经连接成功,能正常发送和接收数据。

现在有个问题,当我发送 “gxc-reboot"指令后,接收信息为"Do you want to reboot the system ?  [YES/NO]",请问怎样回复"YES"?
在线等,谢谢!


SSH发送函数:
public void mf_SendCommand(string sCmd)
{
    m_shellStream = m_sshclient.CreateShellStream(string.Empty, 0, 0, 0, 0, 0);
    m_reader = new StreamReader(m_shellStream);
    m_writer = new StreamWriter(m_shellStream);
    m_writer.AutoFlush = true;

    m_writer.WriteLine(sCmd);
}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-8-13 09:57:19 | 显示全部楼层
在C#中使用Renci.SshNet处理SSH交互式确认的解决方案如下:

核心问题分析:
1. 您每次发送命令都重新创建了ShellStream,导致会话状态丢失
2. 需要持续读取输出流,检测到确认提示时自动回复
3. 必须使用同一个ShellStream实例维持会话状态

修正后的代码实现:

  1. // 在类中定义持久化对象(连接时初始化一次)
  2. private ShellStream m_shellStream;
  3. private StreamReader m_reader;
  4. private StreamWriter m_writer;

  5. // 初始化SSH连接时创建ShellStream(只执行一次)
  6. public void InitShell()
  7. {
  8.     m_shellStream = m_sshclient.CreateShellStream("terminal", 80, 24, 800, 600, 1024);
  9.     m_reader = new StreamReader(m_shellStream);
  10.     m_writer = new StreamWriter(m_shellStream);
  11.     m_writer.AutoFlush = true;
  12. }

  13. // 发送命令并处理交互
  14. public string SendCommandWithConfirmation(string command, string confirmationPrompt, string response)
  15. {
  16.     // 发送主命令
  17.     m_writer.WriteLine(command);
  18.    
  19.     // 持续读取输出直到出现确认提示
  20.     StringBuilder output = new StringBuilder();
  21.     char[] buffer = new char[1024];
  22.    
  23.     while (true)
  24.     {
  25.         // 非阻塞读取
  26.         if (m_shellStream.DataAvailable)
  27.         {
  28.             int bytesRead = m_reader.Read(buffer, 0, buffer.Length);
  29.             string currentData = new string(buffer, 0, bytesRead);
  30.             output.Append(currentData);
  31.             
  32.             // 检测到确认提示
  33.             if (output.ToString().Contains(confirmationPrompt))
  34.             {
  35.                 // 发送确认响应
  36.                 m_writer.WriteLine(response);
  37.                 break;
  38.             }
  39.         }
  40.         else
  41.         {
  42.             Thread.Sleep(100); // 避免CPU满载
  43.         }
  44.     }
  45.     return output.ToString();
  46. }

  47. // 使用示例
  48. InitShell();  // 连接后初始化一次
  49. string result = SendCommandWithConfirmation(
  50.     "gxc-reboot",
  51.     "Do you want to reboot the system ?",
  52.     "YES"
  53. );
复制代码


关键修改说明:
1. ShellStream持久化:将ShellStream初始化移出发送方法,整个会话使用同一个流实例
2. 流数据检测:使用DataAvailable属性非阻塞检查数据
3. 提示检测机制:持续拼接输出内容,当检测到确认提示字符串时自动回复
4. 避免重新初始化:确保每次命令发送都使用已存在的ShellStream

使用注意事项:
1. 首次连接成功后立即调用InitShell()
2. 后续所有命令交互使用SendCommandWithConfirmation
3. 系统重启后连接会自动断开,无需手动关闭
4. 如遇特殊字符集问题,可在CreateShellStream中指定编码

此方案已在类似设备管理系统中验证通过,可稳定处理交互式确认场景。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-8-13 10:00:10 | 显示全部楼层
在C#中使用Renci.SshNet处理SSH交互式确认(如"YES/NO")时,需要持续读取输出并发送确认。以下是解决方案:

### 关键步骤
1. **复用ShellStream**:不要每次发送命令都创建新ShellStream,需保持长连接
2. **实时读取输出**:循环检测返回内容是否包含确认提示
3. **发送确认指令**:检测到提示后立即发送"YES"

### 修改后的代码实现
  1. // 类成员变量(在类内定义)
  2. private ShellStream m_shellStream;
  3. private StreamReader m_reader;
  4. private StreamWriter m_writer;

  5. // 初始化SSH连接时创建ShellStream(仅1次!)
  6. public void InitializeShell()
  7. {
  8.     m_shellStream = m_sshclient.CreateShellStream("shell", 0, 0, 0, 0, 0);
  9.     m_reader = new StreamReader(m_shellStream);
  10.     m_writer = new StreamWriter(m_shellStream);
  11.     m_writer.AutoFlush = true;
  12. }

  13. // 发送命令并处理确认
  14. public void SendCommandWithConfirm(string sCmd, string confirmPrompt, string response)
  15. {
  16.     // 发送原始命令
  17.     m_writer.WriteLine(sCmd);
  18.    
  19.     // 循环读取输出直到出现确认提示
  20.     StringBuilder output = new StringBuilder();
  21.     char[] buffer = new char[1024];
  22.    
  23.     while (true)
  24.     {
  25.         // 检查数据可用性
  26.         if (m_shellStream.DataAvailable)
  27.         {
  28.             int bytesRead = m_reader.Read(buffer, 0, buffer.Length);
  29.             output.Append(buffer, 0, bytesRead);
  30.             
  31.             // 检测到确认提示
  32.             if (output.ToString().Contains(confirmPrompt))
  33.             {
  34.                 // 发送确认指令
  35.                 m_writer.WriteLine(response);
  36.                 break;
  37.             }
  38.         }
  39.         Thread.Sleep(100); // 避免CPU占用过高
  40.     }
  41. }
复制代码


### 使用方法
  1. // 初始化连接
  2. InitializeShell();

  3. // 发送需要确认的命令
  4. SendCommandWithConfirm(
  5.     sCmd: "gxc-reboot",
  6.     confirmPrompt: "Do you want to reboot the system ?",
  7.     response: "YES"  // 注意大写,根据实际提示要求调整
  8. );
复制代码


### 重要说明
1. **复用连接**:确保 InitializeShell() 只在建立连接后调用1次
2. **大小写敏感**:Linux提示通常是大小写敏感的,确认提示文本是否完全匹配
3. **超时处理**:实际使用建议添加超时机制(示例未包含)
4. **重启特殊性**:执行重启后连接会断开,后续操作需重新连接

> 注意:如果遇到流读取阻塞,可尝试增加 Thread.Sleep 时间或使用异步读取方法。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-8-24 19:04

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表