shell脚本解决scp需要输入密码问题

场景:客户要求把96服务器上的数据复制到86服务器上,但是要自动复制,不要人为干预,然后我就登录96服务器,使用ssh命令,登录到86服务器,发现需要输入密码,要想写shell脚本,使用scp命令复制数据的话,需要手动输入密码。

基于此场景,有两个方案。

方案一:96和86服务器配置免密登录

步骤:

1.生成无密码的密钥对

ssh-keygen -t rsa

一路回车

2.将公钥添加到本地认证文件中

cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

3.设置authorized_keys的访问权限

chmod 600 /root/.ssh/authorized_keys

**以上步骤先在每个节点上先执行一遍,然后执行下面操作

4.将每个节点上生成的id_rsa.pub复制到其他所有节点并添加到它们的认证文件中

比如:96上生成的id_rsa.pub,复制到86上

scp /root/.ssh/id_rsa.pub 86:/root/(96上执行)

cat ~/id_rsa.pub >> ~/.ssh/authorized_keys(在86上执行)

scp /root/.ssh/id_rsa.pub 96:/root/(86上执行)

cat ~/id_rsa.pub >> ~/.ssh/authorized_keys(在96上执行)

我查看一下,96和86服务器上都有免密到其他服务器的公钥了,如果我再执行ssh-keygen -t rsa命令,会把之前配置的给覆盖。

我查看到目录:.ssh/下有id_rsa.pub。

第2步的目的其实就是id_rsa.pub内容添加到对方机器的authorized_keys,然后我把86服务器上的 id_rsa.pub内容添加到96机器的authorized_keys,就可以了。如果你按照方案一不能解决问题,那么可以使用方案二,我也是使用的方案二,因为免密配置,配置的次数太多了(我的这篇文章https://blog.csdn.net/Allenzyg/article/details/105762429也有免密配置步骤),也想换个方式。哈哈哈~~~

方案二:使用expect

expect就是用来做交互用的,基本任何交互登录的场合都能使用,但是需要安装expect包。

步骤:

1.在96服务器下载expect

yum -y install expect

2.配置shell脚本

vim 1.sh

填入如下内容:

#!/usr/bin/expect -f

set timeout 30

spawn scp 目录/文件 86:/opt/fanRuan/apache-tomcat-8.5.29/webapps/WebReport/yecai_tctp_income/BL/January/

expect "*password:"

send "123456\r"

expect eof

3.执行1.sh文件

注意:expect跟bash类似,使用时要先登录到expect,所以首行要指定使用expect在运行脚本时候要expect  file,不能sh file了,不然会报错:

1.sh: line 4: spawn: command not found

couldn't read file "*password:": no such file or directory

1.sh: line 6: send: command not found

couldn't read file "eof": no such file or directory

说明执行方式不正确,因为expect用的不是bash所以会报错。执行的时候直接./1.sh就可以了

如果执行./1.sh报错:-bash: ./1.sh: Permission denied

解决办法:chmod -R 777 1.sh

首行指定用来执行该脚本的命令程序,这里是/usr/bin/expect

上面语句第一句是设定超时时间为30s,spawn是expect的语句,执行命令前都要加这句

expect "password:"这句意思是交互获取是否返回password:关键字,因为在执行ssh时会返回输入password的提示:[email protected]'s password:

send就是将密码123456发送过去

expect eof 子进程已经结束的eof字符,expect脚本也就退出结束

interact代表执行完留在远程控制台,不加这句执行完后返回本地控制台

知识储备:linux下expect的使用

使用一:

expect 使用

安装:

yum -y install expect

 

1,首行声明

2,控制台输出

3,设置日期变量$date

4,设置ip变量$local_ip 127.0.0.1

5,设置默认等待时间: 3000

#!/usr/bin/expect -f

set date [exec date "+%Y%m%d"]

set ip1 123.57.219.236

set timeout 3000

 

6,简单交互

spawn

send:用于向进程发送字符串

expect:从进程接收字符串

spawn:启动新的进程

interact:允许用户交互

等待输入"hi\n"

?

输出"hello word\n"

?

expect "hi\n"

send "you typed <$expect_out(buffer)>"

send "but I only expected <$expect_out(0,string)>"

使用二:

当在标准输入中输入

test

hi

是,运行结果如下

you typed: test

hi

I only expect: hi

 

匹配到hi后,会输出"you said hi"

expect "hi" {send "You said hi"}

 

匹配到hi,hello,bye任意一个字符串时,执行相应的输出

expect {

"hi" { send "You said hi\n"}

"hello" { send "Hello yourself\n"}

"bye" { send "That was unexpected\n"}

}

 

这段代码的作用是登录到ftp服务器ftp ftp.uu.net上,并以二进制的方式下载服务器上的文件test.tar.gz。程序中有详细的注释。

set timeout -1

spawn ftp ftp.test.com      //打开新的进程,该进程用户连接远程ftp服务器.最后将控制权交给用户.

expect "Name"             //进程返回Name时

send "user\r"        //向进程输入anonymous\r

expect "Password:"        //进程返回Password:时

send "123456\r"    //向进程输入[email protected]\r

expect "ftp> "            //进程返回ftp>时

send "binary\r"           //向进程输入binary\r

expect "ftp> "            //进程返回ftp>时

send "get test.tar.gz\r"  //向进程输入get test.tar.gz\r

interact

使用三:

ssh免密码登录:123.57.219.236,密码:123456:

spawn ssh -p10022 [email protected]

expect {

"yes/no" {send "yes\r";exp_continue}

"password:" {send "123456\n\r"}

}

interact

 

执行236上指定目录的脚本,可以适配第一次连接:

spawn ssh -p 10022  rsync@$ip1 "expect /data/software/bak/rsync_2_48.sh"

expect {

      "yes/no" { send "yes\r";exp_continue}

      "$ip1's password:" { send "pwd@123\n\r"}

      }

expect eof

使用四:

2,获取执行参数

执行的第一个参数

set nb1 [lindex $argv 0]

# 执行第二个参数

set nb2 [lindex $argv 1]

# 参数数量

puts "$argc"

# 程序名字

puts "$argv0"

3,逻辑判断

switch  分支结构

set color  [lindex $argv 0]

switch  $color  {

        apple {

                puts "apple is blue"

        }

        banana {

                puts "banana is yellow "

        }

}

if 分支

#!/usr/bin/expect

set test [lindex $argv 0]

if { "$test" == "apple" } {

        puts "$test"

} else  {

        puts "not apple"

}

使用五:

for 循环结构

第一种

foreach number {

1

2

3thread

4third

} {

        puts "$number"

}

第二种

 

for {set i 0} {$i<4} {incr i} {

        puts "$i"

}

while  循环结构

set i 1

while {$i<4} {

        puts "$i"

        incr i

}

4 函数定义

proc test {} {

        puts "ok"

}

test

5. 结尾加 interact

  执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行

使用六:

然后在shell脚本中调用即可:

 

#!/bin/bash

expect /root/shell/login.exp agrv1 agrv2

最后的知识储备参考:https://blog.csdn.net/huoyuanshen/article/details/79473063

猜你喜欢

转载自blog.csdn.net/Allenzyg/article/details/107363048