上一篇说到利用expect来访问远程ssh服务器,并输入命令,但是expect有一些不足,而且有些麻烦。使用sshpass这个程序,支持密码作为参数使用,这样方便很多。
我在使用expect的时候,等待的时候比较长,下面介绍一个响应速度快的程序,那就是sshpass。
安装sshpass
这个程序需要自己编译安装,步骤很简单。
从网站上下载代码,http://sourceforge.net/projects/sshpass/
tar -zxvf sshpass-1.05.tar.gz cd sshpass-1.05 ./configure make && make install
这个程序很快就安装完了。
命令参数
接下来我们看看如何使用sshpass。
[root@www ~/sshpass-1.05]# 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 -h Show help (this screen) -V Print version information At most one of -f, -d, -p or -e should be used
结合ssh一起使用
sshpass -p "mypassword" ssh -p 22 user@127.0.0.1 "ls"
这样,通过sshpass参数-p
指定密码,在ssh命令的等待输入密码的时候就能自动将密码写入到输入流中了。
解决著名的第一次问题
在ssh第一次去访问机器的时候,ssh会提示你是否需要将目标ip写入到系统的已知主机中。因为这个的输出会干扰sshpass判断何时应该输入密码。下面程序分析会说。
ssh user@127.0.0.1 The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established. RSA key fingerprint is c4:4e:a1:56:ad:32:a0:b5:90:13:4e:b8:a2:cf:24:a0. Are you sure you want to continue connecting (yes/no)?
通过制定参数-o StrictHostKeyChecking=no
让ssh自动添加到已知主机文件中。
ssh -o StrictHostKeyChecking=no user@127.0.0.1 Warning: Permanently added '127.0.0.1' (RSA) to the list of known hosts. user@127.0.0.1's password:
sshpass底层源码分析
底层的工作原理和expect差不多,都是去等待输出,
int handleoutput( int fd ) { // We are looking for the string static int prevmatch=0; // If the "password" prompt is repeated, we have the wrong password. static int state1, state2; static const char compare1[]="assword:"; // Asking for a password static const char compare2[]="The authenticity of host "; // Asks to authenticate host // static const char compare3[]="WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"; // Warns about man in the middle attack // The remote identification changed error is sent to stderr, not the tty, so we do not handle it. // This is not a problem, as ssh exists immediately in such a case char buffer[40]; int ret=0; int numread=read(fd, buffer, sizeof(buffer) ); state1=match( compare1, buffer, numread, state1 ); // Are we at a password prompt? if( compare1[state1]=='\0' ) { if( !prevmatch ) { write_pass( fd ); state1=0; prevmatch=1; } else { // Wrong password - terminate with proper error code ret=RETURN_INCORRECT_PASSWORD; } } ..... }
优缺点
先说一下不足吧。
1.我使用的Linux是公司修改过的,账户使用LDAP帐号登录(其实我至今还不懂LDAP是什么,但是都这么叫),输入ssh命名后和普通的ssh的不一样。
#### 公司的ssh输出 ssh -p 22 user@10.168.123.145 Keyboard-interactive: PAM authentication Password: Keyboard-interactive: PAM authentication LDAP Password: #### 普通的ssh命令输出 ssh user@localhost user@localhost's password:
所以现在在公司里面没办法使用sshpass,但是在没有修改过的Linux系统上是可以使用sshpass的。这个问题我得找个懂C语言的大神问问。
初步分析好像是公司的Linux经过安全设置,阻止了获取子进程的tty终端,导致无法获取子进程的输出。
2.就是密码放在参数里使用,有些不安全,别人可以使用history
来查看到历史的命令,虽然指定了参数可以从文件中获取,但是这个文件里面也是需要进行权限控制的。
优点就是简单,速度会比使用expect
快很多。
声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客
发表评论