通过scp拷贝文件时无需交互输入密码

 每日运维   2022-02-13 16:32   159 人阅读  0 条评论

工作中经常需要把一些文件从一个服务器传输到另一台服务器,linux环境下最习惯的方式当然是scp,但是scp需要交互输入密码有时候觉得麻烦,记录几种无需手动输入密码的方法。

方法一:建立SSH互信

此方式不仅是方便scp,在可靠系统间此方式也是非常方便的连接方式,具体建立互信操作过程暂略,前面地方有单独记录过了如下:

假设本地主机linux100,远程主机linux200

1、运行 

#ssh-keygen -t rsa

结果如下

QUOTE: 
Generating public/private rsa key pair. 
Enter file in which to save the key (/home/.username/ssh/id_rsa):#回车 
Enter passphrase (empty for no passphrase):#回车 
Enter same passphrase again:#回车 
Your identification has been saved in /home/.username /.ssh/id_rsa. 
Your public key has been saved in /home/.username /.ssh/id_rsa.pub. 
The key fingerprint is: 
38:25:c1:4d:5d:d3:89:bb:46:67:bf:52:af:c3:17:0c username@localhost 
Generating RSA keys: 
Key generation complete.

会在用户目录~/.ssh/产生两个文件,id_rsa,id_rsa.pub 
1、把linux100主机上的id_rsa.pub文件拷贝到linux200主机的root用户主目录下的.ssh目录下,并且改名为authorized_keys 
即: 

/root/.ssh/authorized_keys

这样在linux100主机上使用scp命令复制文件到linux200上将不提示输入密码了,直接复制了。也可在linux100主机上使用scp命令将linux200上文件复制到本机;

总之不需要验证,就可以在linux100访问linux200
反之亦然!

注:如果有多台计算机需要与linux200进行复制,则只需将id_rsa.pub中的内容复制到authorized_keys文件中即可。

执行以下命令将内容追加进去

cat ~/.ssh/a.pub >> ~/.ssh/authorized_keys

3、复制文件或目录命令: 
复制文件: 
(1)将本地文件拷贝到远程 
scp 文件名 用户名@计算机IP或者计算机名称:远程路径 
(2)从远程将文件拷回本地 
scp 用户名@计算机IP或者计算机名称:文件名 本地路径 
复制目录: 
(1)将本地目录拷贝到远程 
scp -r 目录名 --用户名@计算机IP或者计算机名称:远程路径 
(2)从远程将目录拷回本地 
scp -r 用户名@计算机IP或者计算机名称:目录名 本地路径

方法二:使用sshpass工具

建立信任关系的做法是最方便和安全的做法,但是在有些场景下(比如远端的authorized_keys是不能随意更改的),那么这个时候我们就可以借助sshpass这个第三方工具来完成ssh连接时的密码输入。先看一下sshpass的man手册中是如何描述的:

sshpass - noninteractive ssh password provider

从描述上就可以清晰的了解到,sshpass的设计就是为了使用非交互的场景下输入ssh连接的密码。

sshpass的使用比较简单,先看一下帮助文档:

root@localhost:~# 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

其中-p是直接指定密码,-f是从文件中读取密码。那么一个使用sshpass的简单例子就是:

[root@node1 ~]# sshpass -f pa.txt scp index root@192.168.10.22:/var
[root@node1 ~]# sshpass -p root1234 scp config.log root@192.168.10.22:/root/a.lo

使用sshpass的好处就是方便直接,无需了解公私钥、加密认证等相关知识,简单易懂;但是使用sshpass最大的坏处就是在使用时会涉及到明文密码,大大降低了安全性。

方式三:使用expect脚本来输入密码

expect用于自动化地执行linux环境下的命令行交互任务,例如scp、ssh之类需要用户手动输入密码然后确认的任务。有了这个工具,定义在scp过程中可能遇到的情况,然后编写相应的处理语句,就可以自动地完成scp操作了。

下面就是一个使用expect来完成scp时无需输入密码的脚本:

#!/usr/bin/expect
set timeout
set host [lindex $argv ]
set username [lindex $argv ]
set password [lindex $argv ]
set src_file [lindex $argv ]
set dest_file [lindex $argv ]
spawn scp $src_file $username@$host:$dest_file
expect {
"(yes/no)?"
 {
   send "yes\n"
   expect "*assword:" { send "$password\n"}
 }
"*assword:"
 {
   send "$password\n"
 }
}
expect "100%"
expect eof  

意代码刚开始的第一行,指定了expect的路径,与shell脚本相同,这一句指定了程序在执行时到哪里去寻找相应的启动程序。代码刚开始还设定了timeout的时间为10秒,如果在执行scp任务时遇到了代码中没有指定的异常,则在等待10秒后该脚本的执行会自动终止。

从以上代码刚开始的几行可以看出,我为这个脚本设置了5个需要手动输入的参数,分别为:目标主机的IP、用户名、密码、本地文件路径、目标主机中的文件路径。如果将以上脚本保存为expect_scp文件,则在shell下执行时需要按以下的规范来输入命令:

./expect_scp 192.168.10.21 root  /root/src_file /root/dest_file 

以上的命令执行后,将把本地/root目录下的src_file文件拷贝到用户名为root,密码为123456的主机192.168.10.21中的/root下,同时还将这个源文件重命名为dest_file。

spawn代表在本地终端执行的语句,在该语句开始执行后,expect开始捕获终端的输出信息,然后做出对应的操作。expect代码中的捕获的(yes/no)内容用于完成第一次访问目标主机时保存密钥的操作。有了这一句,scp的任务减少了中断的情况。代码结尾的expect eof与spawn对应,表示捕获终端输出信息的终止。

使用expect需要了解的一点是:用expect速度会比较慢,因为需要等待返回的数据,然后输入命令执行,没有ssh密钥登录的快速。

安全性和速度上考虑建立信任关系都是最佳的方法,至于在具体的环境中选择什么根据实际情况来选择。

本文地址:https://linux365.cn/post/65.html
版权声明:本文为原创文章,版权归 每日运维 所有,欢迎分享本文,转载请保留出处!

评论已关闭!