|
发表于 2025-8-13 09:57:19
|
显示全部楼层
在C#中使用Renci.SshNet处理SSH交互式确认的解决方案如下:
核心问题分析:
1. 您每次发送命令都重新创建了ShellStream,导致会话状态丢失
2. 需要持续读取输出流,检测到确认提示时自动回复
3. 必须使用同一个ShellStream实例维持会话状态
修正后的代码实现:
- // 在类中定义持久化对象(连接时初始化一次)
- private ShellStream m_shellStream;
- private StreamReader m_reader;
- private StreamWriter m_writer;
- // 初始化SSH连接时创建ShellStream(只执行一次)
- public void InitShell()
- {
- m_shellStream = m_sshclient.CreateShellStream("terminal", 80, 24, 800, 600, 1024);
- m_reader = new StreamReader(m_shellStream);
- m_writer = new StreamWriter(m_shellStream);
- m_writer.AutoFlush = true;
- }
- // 发送命令并处理交互
- public string SendCommandWithConfirmation(string command, string confirmationPrompt, string response)
- {
- // 发送主命令
- m_writer.WriteLine(command);
-
- // 持续读取输出直到出现确认提示
- StringBuilder output = new StringBuilder();
- char[] buffer = new char[1024];
-
- while (true)
- {
- // 非阻塞读取
- if (m_shellStream.DataAvailable)
- {
- int bytesRead = m_reader.Read(buffer, 0, buffer.Length);
- string currentData = new string(buffer, 0, bytesRead);
- output.Append(currentData);
-
- // 检测到确认提示
- if (output.ToString().Contains(confirmationPrompt))
- {
- // 发送确认响应
- m_writer.WriteLine(response);
- break;
- }
- }
- else
- {
- Thread.Sleep(100); // 避免CPU满载
- }
- }
- return output.ToString();
- }
- // 使用示例
- InitShell(); // 连接后初始化一次
- string result = SendCommandWithConfirmation(
- "gxc-reboot",
- "Do you want to reboot the system ?",
- "YES"
- );
复制代码
关键修改说明:
1. ShellStream持久化:将ShellStream初始化移出发送方法,整个会话使用同一个流实例
2. 流数据检测:使用DataAvailable属性非阻塞检查数据
3. 提示检测机制:持续拼接输出内容,当检测到确认提示字符串时自动回复
4. 避免重新初始化:确保每次命令发送都使用已存在的ShellStream
使用注意事项:
1. 首次连接成功后立即调用InitShell()
2. 后续所有命令交互使用SendCommandWithConfirmation
3. 系统重启后连接会自动断开,无需手动关闭
4. 如遇特殊字符集问题,可在CreateShellStream中指定编码
此方案已在类似设备管理系统中验证通过,可稳定处理交互式确认场景。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|