C++调用system()执行ssh命令时如何自动输入密码及交互命令
问题原因分析
你原有代码失效的核心原因有两个:
system()函数是同步阻塞执行的,只有当前面的命令执行完成(也就是ssh连接退出后)才会运行下一条命令,天然无法在ssh运行过程中输入内容- ssh客户端默认直接从
/dev/tty设备读取密码,不会读取进程的标准输入,哪怕你用popen往ssh进程的标准输入写内容,也没法完成密码输入,这个方案天然走不通。
可行实现方案
方案1:借助sshpass工具(最简实现)
sshpass是专门用于非交互方式给ssh传递密码的工具,可以绕过ssh读tty的限制。
使用步骤
- 先安装sshpass:
- Debian/Ubuntu系:
apt install sshpass - RHEL/CentOS系:
yum install sshpass - macOS:
brew install hudochenkov/sshpass/sshpass
- Debian/Ubuntu系:
- C++代码调整示例:
#include<iostream> #include<string> #include<stdlib.h> using namespace std; int main() { string user = "user"; string password = "你的实际密码"; string forwarded = "0.tcp.ngrok.io"; string port = "00000"; // 要在ssh服务端执行的命令,多条命令用分号分隔 string remote_cmd = "ls -la; pwd; whoami"; // 拼接完整命令 string command = "sshpass -p '" + password + "' ssh " + user + "@" + forwarded + " -p " + port + " '" + remote_cmd + "'"; system(command.c_str()); return 0; }
注意事项
- 该方案密码会明文出现在进程命令行中,同主机的其他用户可以通过
ps命令查看到,仅适合测试/内网可信环境使用,生产环境禁止使用。 - 如果不需要执行完命令就退出ssh,可以去掉末尾的remote_cmd部分,加
-t参数强制分配tty,就能进入交互模式。
方案2:使用libssh库(推荐生产环境使用)
直接调用原生SSH库完成连接、认证、命令执行全流程,不需要依赖外部ssh命令,安全性和可控性更高,不需要处理输入输出重定向问题。官方提供了完整的密码认证、执行远程命令的示例代码,稳定性有保障。
方案3:基于伪终端(PTY)自主实现交互
如果你不想依赖第三方工具/库,可以自己创建伪终端,将ssh进程的标准输入、输出、错误流全部绑定到伪终端从设备,你通过伪终端主设备就可以像真人操作一样输入密码、后续执行命令,完全模拟交互流程,但实现复杂度较高。
常见疑问解答
- 密码传入后可以继续执行后续命令:不管用上述哪个方案,都支持传入密码后执行任意多条远程命令,也可以保持ssh会话长期存在,按需下发命令。
内容的提问来源于stack exchange,提问作者Manoel Augusto
相关产品推荐
相关产品推荐

