SSHPASS 的使用

2019/08/13 ssh Linux

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)

ssh 相关更多工具

Search

    Table of Contents