先说一个经常被踩的坑:sshpass 虽然能帮你自动填写密码,但首次连接远程主机时,真正卡住你的往往不是密码输入框,而是那个“是否接受主机密钥”的确认提示。这是一个典型“知道就不难”的问题——如果不处理这个环节,命令会直接挂起或返回非零退出码。解决办法只有两种:要么临时跳过主机验证,要么提前把远程主机指纹存入本地的 known_hosts 文件。

安装 sshpass 时务必确认系统源与依赖状态
大多数主流 Linux 发行版默认不会预装 sshpass,需要手动配置软件仓库或编译安装——常见场景如下:
- CentOS/RHEL/BCLinux:先启用 EPEL 源(
yum install epel-release),再执行yum install sshpass - Ubuntu/Debian:直接使用
apt-get install sshpass,简洁高效 - 如果包管理器无法找到,可以去 SourceForge 下载 tar 包(例如
sshpass-1.09.tar.gz),解压后运行./configure && make && sudo make install - 安装完成后用
sshpass -V验证;若提示“command not found”,可能是安装路径在/usr/local/bin但 PATH 未包含——创建软链接或更新 PATH 即可解决
密码传递别只依赖 -p,选对方式更安全
-p 参数最直观,但明文密码会暴露在 ps 进程列表和 shell 历史记录中,生产环境切勿使用。更稳妥的方案有三种:
- 使用
-f从文件读取:创建pwd.txt(权限设为600),文件内只放一行密码,然后运行sshpass -f pwd.txt ssh user@host - 使用
-e读取环境变量:先执行export SSHPASS="your_pass",再运行sshpass -e ssh user@host;注意该变量不会被子 shell 继承,需在同一个 shell 环境内执行 - 使用
-d从文件描述符读取:脚本中可用exec 3<<<"$PASS"然后sshpass -d 3 ssh ...,稍复杂但能避免密码被ps窥探
StrictHostKeyChecking=no 不是万能钥匙,需要搭配使用
首次连接远程主机时,SSH 客户端默认会阻断并等待你输入 yes。仅靠 -p 密码无法绕过这个卡点,必须配合 SSH 自身的选项:
- 临时跳过主机验证(仅适用于可信内网):
sshpass -e ssh -o StrictHostKeyChecking=no user@host - 更安全的方法:提前用
ssh-keyscan host >> ~/.ssh/known_hosts将远程主机指纹写入本地数据库,后续所有sshpass命令都不会再出现提示 - 如果目标主机 IP 频繁变动(例如 DHCP 环境),
StrictHostKeyChecking=no几乎成为唯一选择,但前提是网络必须物理隔离,以防止中间人攻击 - 常见反面案例:
sshpass -p xxx scp ...未加-o StrictHostKeyChecking=no,导致返回码 6(可通过echo $?查看)
scp 与 ssh 命令的参数顺序极易出错
sshpass 本身不解析远程命令,只负责将密码“喂”给后面的 ssh 或 scp 进程。参数顺序和嵌套关系是最高频的翻车点:
- 正确写法:
sshpass -e scp -o StrictHostKeyChecking=no file user@host:/path/——-o属于scp,必须紧跟在scp之后 - 错误示范:
sshpass -o StrictHostKeyChecking=no -e scp ...——sshpass无法识别-o,直接报错 - 远程执行多条命令时,整个命令字符串要用单引号包裹:
sshpass -e ssh user@host 'df -h && uptime';若使用双引号,本地 shell 会先展开变量,容易引发异常 - 指定非标准端口:使用
ssh -p 2222,而非ssh --port=2222;scp同理,只是参数为大写的-P
说到底,真正的麻烦从来不是输入密码本身,而是首次连接时那个没人提前告知你要处理的 yes/no 确认提示,以及密码最终流向了哪个进程、被谁看到。别省那两行 ssh-keyscan 命令,它比单纯依赖 StrictHostKeyChecking=no 能减少一半的安全风险。
