【linux 】 解决脚本中scp需要手动输入密码问题

1、解决方法
命令行scp拷贝文件需要输入密码,如果想在脚本里自动化scp拷贝,可以用expect来实现自动化操作。
例子1.1:
将本机/home/test.txt文件拷贝到目标机器xx.xx.xx.xx的/home目录下
#!/bin/bash
function scp_file {
local file=$1
local passwd="xxxxxx" # xx.xx.xx.xx机器的密码
expect -c"
spawn scp -r ${file} root@xx.xx.xx.xx:/home
expect {
\"*assword\" {set timeout 300; send \"${passwd}\r\";}
}
expect eof"
}
scp_file "/home/test.txt"
2、知识点
2.1 expect工具
expect命令可以用于处理自动交互场景,比如scp时,让你手动输入密码,使用expect就可以自动输入密码,避免手动输入。
expect中有定义一些命令,做如下总结:
expect: expect工具的内部命令。它的主要功能是判断上一次输出结果里是否含有“xxxx”指定的字符串。
spawn: spawn时进入expect环境后才可以执行的expect内部命令,它的主要功能时用来传递交互指令。
send:发送信息,模拟用户手动输入这一过程,最后要添加\r。表示返回到当前行的最开始位置。
exp_continue: 使用exp_continue之后,会重新从当前expect块的开始重新执行。
expect eof: 执行完expect中的命令后退出。
3、遇到的问题
3.1 expect: spawn id exp4 not open while executing "expect eof"
原因:spawn出来的进程在expect eof的时候,已经结束了。
解决方法:
检查expect eof之前,spawn生成的进程是否已经结束。
以例子1.1说明,如果程序修改为如下样子,就会报错:expect: spawn id exp4 not open while executing "expect eof",而将exp_continue;删除就不会报错。
#!/bin/bash
function scp_file {
local file=$1
local passwd="xxxxxx" # xx.xx.xx.xx机器的密码
expect -c"
spawn scp -r ${file} root@xx.xx.xx.xx:/home
expect {
\"*assword\" {set timeout 300; send \"${passwd}\r\"; exp_continue;}
}
expect eof"
}
scp_file "/home/test.txt"
这是因为expect已经执行了一次,exp_continue会重新执行一次expect块,而前一次的expect已经处理了spawn这个进程的返回值,你再重新执行,spawn生成的进程已经结束了,因此报错。删掉exp_continue,处理完就退出,不要再循环执行expect了。