libssh执行远程命令必须手动构造会话、认证、通道并循环读取标准流;需显式设置超时、主机验证策略、端口及密钥选项;认证失败须重连;每次命令需新建channel并完整走open→exec→read→close流程。

libssh 本身不提供“执行远程命令”的高层封装,必须手动构造会话、认证、通道并处理标准流——直接调用 ssh_channel_request_exec 是唯一可靠路径,别指望类似 python paramiko 那样的 exec_command 一键函数。
初始化会话与连接前必须显式设置超时和主机验证策略
libssh 默认拒绝连接未知主机,且无默认连接/读写超时,不设会卡死。常见错误是跳过 ssh_options_set 或误用 SSH_OPTIONS_HOST 拼接端口(应单独设 SSH_OPTIONS_PORT)。
- 必须调用
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &timeout_sec),否则ssh_connect可能永久阻塞 - 若跳过主机密钥验证(如测试环境),需设
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, ""),而非留空或忽略 - 主机名不能带
ssh://前缀,端口必须用SSH_OPTIONS_PORT单独传整数,不能写在 host 字符串里
密码认证失败常因未调用 ssh_userauth_password 或忽略返回值
libssh 的认证是状态机驱动,ssh_userauth_password 返回 SSH_AUTH_SUCCESS 才算成功;返回 SSH_AUTH_DENIED 后不能重试同一 session,必须断开重连。
- 必须检查返回值:
if (ssh_userauth_password(session, NULL, password) != SSH_AUTH_SUCCESS) - 密码含特殊字符(如
@、/)无需转义,libssh 不解析 URL 格式 - 公钥认证更稳定,推荐用
ssh_userauth_publickey_file,私钥路径必须为绝对路径或确保当前工作目录正确
执行命令后必须主动读取 stdout/stderr 并关闭 channel
ssh_channel_request_exec 仅发起请求,不自动收数据;不循环 ssh_channel_read 会导致命令看似“没输出”,实际已执行但缓冲区滞留。
立即学习“C++免费学习笔记(深入)”;
- 每次
ssh_channel_read最多读buffer_size字节,需循环直到返回 0(EOF)或负值(错误) - 务必在读完后调用
ssh_channel_send_eof和ssh_channel_close,否则下次 channel 复用可能失败 - 命令含管道或后台进程(如
nohup cmd &)时,ssh_channel_is_eof可能立即返回 true,需结合ssh_channel_get_exit_status判断是否真结束
最易被忽略的是 channel 生命周期管理:一个 ssh_channel 对象不能跨多次 ssh_channel_request_exec 复用,每次命令都应新建 channel 并完整走 open → exec → read → close 流程。libssh 不做自动资源回收,漏关 channel 会导致连接句柄泄漏,几次后触发服务器拒绝新连接。