使用Elixir SSHEx框架无法读取网络交换机SSH命令响应问题
问题原因及解决方法
核心原因
- SSHEx的
cmd!方法不兼容交换机交互式CLI:cmd!设计用于执行后自动退出的命令(如Linux的echo),但网络交换机的CLI执行命令后不会自动关闭通道,而是停在提示符,导致SSHEx一直等待通道关闭信号,最终超时。 - 直接调用
:ssh时未完整接收消息:交换机的输出会分多段发送,且初始可能附带SCP服务禁用的提示,你之前只接收了一次消息,未获取到show ssh的实际输出。 - 算法配置不完全匹配手动SSH:手动连接用的是
diffie-hellman-group1-sha1,但SSHEx初始配置仅添加了diffie-hellman-group-exchange-sha1,虽能建立连接,但可能影响后续交互稳定性。
解决方法
方法1:适配SSHEx的交互式shell模式
改用SSHEx.shell进入交互式会话,匹配交换机提示符后发送命令并读取输出:
defmodule FibreTestUi.Ssh do defp connect do SSHEx.connect( ip: '192.168.1.1', user: 'admin', password: '!Password', modify_algorithms: [ {:append, [{:kex, [:diffie-hellman-group1-sha1, :diffie-hellman-group-exchange-sha1]}]}, {:append, [{:public_key, [:ssh-rsa, :ssh-dss]}]} ] ) end def list_port_status do {:ok, conn} = connect() # 匹配交换机的提示符FS# {:ok, shell} = SSHEx.shell(conn, prompt: ~r/FS#/) # 发送命令 SSHEx.send(shell, 'show ssh') # 读取直到提示符再次出现 output = SSHEx.recv(shell, 15000) SSHEx.close(shell) output end end
方法2:完善:ssh模块的消息接收逻辑
循环接收所有SSH消息,直到通道关闭,确保获取完整输出:
defmodule FibreTestUi.Ssh do def send_command do {:ok, ssh_pid} = :ssh.connect('192.168.1.1', 22, user: 'admin', save_accepted_host: false, silently_accept_hosts: true, password: '!Password', modify_algorithms: [ prepend: [kex: [:diffie-hellman-group1-sha1, :diffie-hellman-group-exchange-sha1]], prepend: [public_key: [:ssh-rsa, :ssh-dss]] ] ) {:ok, chn} = :ssh_connection.session_channel(ssh_pid, 5000) :ok = :ssh_connection.exec(ssh_pid, chn, 'show ssh', 5000) output = receive_all(ssh_pid, chn, []) :ssh.close(ssh_pid) output end defp receive_all(ssh_pid, chn, acc) do receive do {:ssh_cm, ^ssh_pid, {:data, ^chn, _, data}} -> receive_all(ssh_pid, chn, [data | acc]) {:ssh_cm, ^ssh_pid, {:eof, ^chn}} -> acc |> Enum.reverse() |> IO.iodata_to_binary() {:ssh_cm, ^ssh_pid, {:exit_status, ^chn, _}} -> receive_all(ssh_pid, chn, acc) {:ssh_cm, ^ssh_pid, {:closed, ^chn}} -> acc |> Enum.reverse() |> IO.iodata_to_binary() after 15000 -> acc |> Enum.reverse() |> IO.iodata_to_binary() end end end
方法3:检查交换机SSH配置
- 确认交换机允许通过SSH执行
exec命令,部分设备默认仅开启交互式shell; - 关闭强制SCP的相关配置,避免无关提示干扰命令输出。
内容的提问来源于stack exchange,提问作者Gareth Jeanne
相关产品推荐
相关产品推荐

