SSHPASS 的使用
如果是常规使用 ssh 登陆到服务器上,要么是通过密码,要么是通过配置公密钥的适配来做到免密登陆。现在有个新的场景,你想通过 ssh 登陆到某台节点并执行一条指令,但不想因为这么简单的事而将公钥上传过去,同时也不想通过 expect 或者 EOF 的方式来模拟操作(我们假定在一个脚本中),这时候就需要 sshpass
的帮助了。
sshpass 是一个简单、轻量级的命令行工具,通过它我们能够向命令提示符本身提供密码(非交互式密码验证),它直接使用 TTY 访问,以确保密码是用户键盘输入的。 sshpass 在专门的 tty 中运行 ssh,以误导 ssh 相信它是从用户接收到的密码。
重要:使用 sshpass 是不安全的,但新版本的 sshpass 做得足够好了。
安装
- RedHat/CentOS 安装
$ yum install sshpass
$ dnf install sshpass [Fedora 22 及以上版本]
- Debian/Ubuntu 和它的衍生版
$ sudo apt-get install sshpass
- MacOSX 安装
截止 2019.8.13 日,最新版是 1.06,未来可能更新,下面的指令,Cellar位置可能不确定。
$ brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb
$ cd /usr/local/bin
$ ln -s sshpass ../Cellar/sshpass/1.06/bin/sshpass
- 源码安装
$ wget http://sourceforge.net/projects/sshpass/files/latest/download -O sshpass.tar.gz
$ tar -xvf sshpass.tar.gz
$ cd sshpass-1.06
$ ./configure
$ sudo make install
使用
sshpass 与 ssh 一起使用。先通过 -h
参数看下 sshpass 能做什么。
$ sshpass
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
-f filename Take password to use from file
-d number Use number as file descriptor for getting password
-p password Provide password as argument (security unwise)
-e Password is passed as env-var "SSHPASS"
With no parameters - password will be taken from stdin
-P prompt Which string should sshpass search for to detect a password prompt
-v Be verbose about what you're doing
-h Show help (this screen)
-V Print version information
At most one of -f, -d, -p or -e should be used
使用用户名和密码登录到远程 Linux ssh 服务器(1.1.1.1),并检查文件系统磁盘使用情况,如图所示。
$ sshpass -p 'testq' ssh root@1.1.1.1 'df -h'
可以看到结果:
[root@localhost ~]# sshpass -p 'testq' ssh root@1.1.1.1 'df -h'
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/VolGroup-root 50G 23G 28G 46% /
devtmpfs 173G 0 173G 0% /dev
tmpfs 173G 640M 173G 1% /dev/shm
tmpfs 173G 4.1G 169G 3% /run
tmpfs 173G 0 173G 0% /sys/fs/cgroup
/dev/loop0 3.8G 3.8G 0 100% /mnt/rhel
/dev/sda2 492M 192M 300M 39% /boot
/dev/mapper/VolGroup-opt 100G 98G 3.0G 98% /opt
/dev/mapper/VolGroup-home 50G 12G 39G 23% /home
/dev/mapper/VolGroup-oswbb 50G 9.9G 41G 20% /oswbb
tmpfs 35G 0 35G 0% /run/user/0
tmpfs 35G 0 35G 0% /run/user/701
这个的运行结果就像是直接通过 ssh -tt 来实现的,但去掉了密码输入以及退出提示,换言之,标准输出流更好地被解析,下面的是通过 ssh -tt 来查询的结果。
[root@localhost ~]# ssh 1.1.1.1 -tt 'df -h'
root@1.1.1.1's password:
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/VolGroup-root 50G 23G 28G 46% /
devtmpfs 173G 0 173G 0% /dev
tmpfs 173G 640M 173G 1% /dev/shm
tmpfs 173G 4.1G 169G 3% /run
tmpfs 173G 0 173G 0% /sys/fs/cgroup
/dev/loop0 3.8G 3.8G 0 100% /mnt/rhel
/dev/sda2 492M 192M 300M 39% /boot
/dev/mapper/VolGroup-opt 100G 98G 3.0G 98% /opt
/dev/mapper/VolGroup-home 50G 12G 39G 23% /home
/dev/mapper/VolGroup-oswbb 50G 9.9G 41G 20% /oswbb
tmpfs 35G 0 35G 0% /run/user/0
tmpfs 35G 0 35G 0% /run/user/701
Connection to 1.1.1.1 closed.
但如果是通过 sshpass 输入密码创建了 ssh 服务通道后,通过 ps -ef|grep sshpass
可以看到刚刚输入的密码的位数,这在某方面来说,具有不安全性,所以不推荐在生产环境这么弄。看下结果。
[root@localhost ~]# ps -ef|grep sshpass
root 2493 2447 0 14:41 pts/1 00:00:00 sshpass -p zzzzz ssh root@1.1.1.1
root 2496 2468 0 14:41 pts/2 00:00:00 grep --color=auto sshpass
这时就要用到密码传递的技术,将密码文件存于文件中或者指定到当前session的某个变量中。
- 将密码存在文件中。
sshpass -f filename ssh 1.1.1.1
- 将密码存在变量中。
SSHPASS=xxxx sshpass -e ssh 1.1.1.1
更推荐第二种方法,因为变量仅存在当前 session 中,所以从其他地方登陆的几乎没任何方法(当然history里还是存储了信息。。只有清理下history了。。。)。
还有一种 -d number
参数,但我查了相关的中文资料,英文资料,几乎没有这么用的,它的原始解释是:number 是 sshpass 从 runner 继承的文件描述符。 从打开的文件描述符中读取密码。问题就是这个 runner 到底是什么,查了些资料也是没有头绪。初步的猜测是和当前 ssh 连接本身有关系。
sshpass 和 scp 的合作:
有两种方式:
- sshpass -p xxxx scp /file/path/filename username@hostname:/remote/path/
- scp /file/path/filename –rsh=”sshpass -p ‘xxxx’ ssh -l test” hostname:/remote/path/
本质上两者区别不大,只是第二种方式在一些网站看到,但不给解释,我就很难受,ssh -l 的意思是指定远端主机的登录名(logname)