由于工作中,经常需要ssh连接到产线服务器进行代码调试。中间经过3层,4层甚至更多层跳转。这就导致在实际操作时常常面临两个问题:
https://github.com/pedroqin/Multi-layer-scp
此脚本工具的实现主要依靠expect
:
Expect is a program that "talks" to other interactive programs
according to a script. Following the script, Expect knows what can be
expected from a program and what the correct response should be. An
interpreted language provides branching and high-level control
structures to direct the dialogue. In addition, the user can take
control and interact directly when desired, afterward returning control
to the script.
而expect采用TCL(即 Tool Command Language 工具脚本语言)开发,故用TCL中语法实现部分逻辑。
以 从多层远端服务器传输文件到本地 为例,在实现的逻辑上,为了实现多层服务器传输功能的统一部署,在expect脚本代码实现上采用了类似递归调用的方式:在本地运行 transfer_file.sh 脚本,并依次带入各层跳转服务器的username
/IP
/passwd
等信息作为参数,而后在每层的跳转服务器自动调用脚本 transfer_file.sh 完成文件传输 。
transfer_file.sh :
#!/usr/bin/expect
###############################################
# Author : PedroQin
# Date : 2020-04-26 20:26:20
# Description :
# Version : 1.0.0
###############################################
#if {$argc <3} {
# puts "Usage: cmd <username> <host> <passwd> <file>"
# exit 1
#}
set timeout -1
set my_name $argv0
set file_name [lindex $argv 0]
set username [lindex $argv 1]
set host [lindex $argv 2]
set passwd [lindex $argv 3]
set remain_argv [lrange $argv 4 999]
set basename [lindex [split "$file_name" "/"] end]
if {$remain_argv!=""} {
spawn ssh $username@$host
expect {
"yes/no" { send "yes\n"; exp_continue}
"$host's password:" { send "$passwd\n" ; exp_continue}
"*#" { send "$my_name $file_name $remain_argv && wait && sync && exit\n" ; exp_continue}
}
spawn scp -r $username@$host:/tmp/$basename /tmp/
expect {
"yes/no" { send "yes\n"; exp_continue}
"$host's password:" { send "$passwd\n" ; exp_continue}
}
} else {
spawn scp $username@$host:$file_name /tmp/
expect {
"*#" { send "sync && exit\n"}
}
}
以下以 4层远端服务器传输文件到本地 作为例子讲解:
/root/transfer_file.sh /root/startservices.sh root 192.168.1.1 123456 root 192.168.2.1 123456 root 192.168.3.1 123456 root 192.168.4.1 123456
,其中/root/startservices.sh
为传输的文件参数,其后为每层跳转机用户名,IP和密码if
判断带入参数中第5到999个参数不为空,即说明还有server要登陆,则继续登入 server2(192.168.2.1) ,检测到“*#”关键字,执行server2上 transfer_file.sh ...if
判断带入参数中第5到999个参数为空,说明已经完成所有server的登陆,则直接从 目标机server4(192.168.4.1) scp 文件到server3 /tmp
下,ssh
命令的expect
,继续执行ssh
之后的scp
,复制server3 的文件到server2 /tmp
下,至此server2的 transfer_file.sh执行完成,退出到server1...scp
文件到本地/tmp
,整个scp过程完成由以上逻辑可以看出,功能实现主要有以下要素:
/root/transfer_file.sh
,后续实现一键部署时,该脚本名称会被替换成命令transfer_file
/root/startservices.sh
,当到达server3,即最后一层跳转服务器后,使用该文件路径获取文件,剩下每层跳转服务器复制文件时将文件copy到 /tmp
下,直至copy到本地/tmp
以下为测试脚本功能时log记录,其中登录到server2 和server3 执行/root/transfer_file.sh
时有多余打印,此为上层跳转服务器expect
匹配,可加判断进行精确匹配,以避免此问题
[root@diag ~]# /root/transfer_file.sh /root/startservices.sh root 192.168.1.1 123456 root 192.168.2.1 123456 root 192.168.3.1 123456 root 192.168.4.1 123456
spawn ssh root@192.168.1.1
root@192.168.1.1's password:
Last login: Tue Apr 28 12:36:54 2020 from 10.67.18.82
[root@server1 ~]# /root/transfer_file.sh /root/startservices.sh root 192.168.2.1 123456 root 192.168.3.1 123456 root 192.168.4.1 123456 && wait && sync && exit
spawn ssh root@192.168.2.1
root@192.168.2.1's password:
Last login: Tue Apr 28 14:15:55 2020 from 172.22.0.66
SIOCADDRT: No such process
[root@server2 ~]# /root/transfer_file.sh /root/startservices.sh root 192.168.2.1 123456 root 192.168.3.1 123456 root 192.168.4.1 123456 && wait && sync && exit
/root/transfer_file.sh /root/startservices.sh root 192.168.3.1 123456 root 192.168.4.1 123456 && wait && sync && exit
spawn ssh root@192.168.3.1
root@192.168.3.1's password:
Last login: Tue Apr 28 13:35:13 2020 from 172.21.35.2
[root@server3 ~]# /root/transfer_file.sh /root/startservices.sh root 192.168.4.1/root/transfer_file.sh /root/startservices.sh root 192.168.2.1 123456 root 192.168.3.1 423456 root 192.168.4.1 123 123456 && wait && sync && /root/transfer_file.sh /root/startservices.sh root 192.168.3.1 123456 root 192.168.4.1 123456 && wait && sync && exit
exit
56 && wait && sync && exit
spawn scp root@192.168.4.1:/root/startservices.sh /tmp/
startservices.sh 100% 334 1.0MB/s 00:00
logout
Connection to 192.168.3.1 closed.
spawn scp -r root@192.168.3.1:/tmp/startservices.sh /tmp/
root@192.168.3.1's password:
startservices.sh 100% 334 0.3KB/s 00:00
logout
Connection to 192.168.2.1 closed.
spawn scp -r root@192.168.2.1:/tmp/startservices.sh /tmp/
root@192.168.2.1's password:
startservices.sh 100% 334 0.3KB/s 00:00
logout
Connection to 192.168.1.1 closed.
spawn scp -r root@192.168.1.1:/tmp/startservices.sh /tmp/
root@192.168.1.1's password:
startservices.sh 100% 334 0.3KB/s 00:00
<route> <!-- the route to server -->
<to_server_2 1 > 2 /> <!-- local(1) to server2 -->
<to_server_3 1 > 2 > 3 />
<to_server_4 1 > 2 > 3 > 4 />
<to_server_5 1 > 2 > 3 > 4 > 5 />
<to_server_6 1 > 2 > 3 > 4 > 6 /> <!-- local(1) to server6 -->
</route>
<common>
<command>transfer_file</command> <!-- the expect script name -->
<dir>/tmp</dir> <!-- the path which transfer server save files in -->
</common>
<server_info>
<server.1 item="local server"> <!-- server name -->
<username>root</username> <!-- username -->
<IP>192.168.0.1</IP> <!-- ip address -->
<passwd>123456</passwd> <!-- passwd -->
<hostname>local</hostname> <!-- hostname -->
</server.1>
...
<server.6 item="server 5">
<username>root</username>
<IP>192.168.5.1</IP>
<passwd>123456</passwd>
<hostname>server5</hostname>
</server.6>
</server_info>
简单写个安装脚本 install.sh
,主要内容如下,主要完成包的解压和可执行文件的配置。
print_run "tar -xf /tmp/multi_scp.tgz -C /tmp"
print_run "cp /tmp/multi_scp/transfer_file.sh /usr/bin/transfer_file" || install_fail
print_run "(cd /usr/bin; chmod +x transfer_file)"
print_run "cp /tmp/multi_scp/multi_scp.sh /usr/bin/multi_scp" || install_fail
print_run "(cd /usr/bin; chmod +x multi_scp)"
print_run "cp /tmp/multi_scp/multi_scp_conf.xml /etc" || install_fail
print_run "rm -rf /tmp/multi_scp*"
打包成一个文件install_multi_scp.run
:
[root@diag ~]# ls multi_scp
multi_scp.sh multi_scp_conf.xml transfer_file.sh
[root@diag ~]# tar -zcf multi_scp.tgz multi_scp/
[root@diag ~]# cat install.sh multi_scp.tgz > install_multi_scp.run
[root@diag ~]# ls
install.sh install_multi_scp.run multi_scp multi_scp.tgz
需要在本地及中转机执行以下操作
install_multi_scp.run
/root/StorageStressTest.pyc
文件传输到远端(故方式为send
)服务器(id为5)上,命令:multi_scp -t 5 -m s -f /root/StorageStressTest.pyc
。
命令运行完毕后,文件从本地/root
传输到远端服务器/tmp
下,中间跳转服务器将文件保存在/tmp
[root@diag ~]# multi_scp -t 5 -m send -f /root/StorageStressTest.pyc
transfer_file send /tmp /root/StorageStressTest.pyc 0 ID.2 root 192.168.1.1 123456 server1 ID.3 root 192.168.2.1 123456 server2 ID.4 root 192.168.3.1 123456 server3 ID.5 root 192.168.4.1 123456 server3
1. scp to ID.2 192.168.1.1 ##**==++==**## ==> spawn scp -r /root/StorageStressTest.pyc root@192.168.1.1:/tmp/
root@192.168.1.1's password:
StorageStressTest.pyc 100% 39KB 38.7KB/s 00:00
1. ssh to ID.2 192.168.1.1 ##**==++==**## ==> spawn ssh root@192.168.1.1
root@192.168.1.1's password:
Last login: Tue Apr 28 15:17:17 2020 from 10.67.18.82
[root@server1 ~]# /usr/bin/transfer_file send /tmp /root/StorageStressTest.pyc 1 ID.3 root 192.168.2.1 123456 server2 ID.4 root 192.168.3.1 123456 server3 ID.5 root 192.168.4.1 123456 server3 && wait && sync && exit
2. scp to ID.3 192.168.2.1 ##**==++==**## ==> spawn scp -r /tmp/StorageStressTest.pyc root@192.168.2.1:/tmp/
root@192.168.2.1's password:
StorageStressTest.pyc 100% 39KB 38.7KB/s 00:00
2. ssh to ID.3 192.168.2.1 ##**==++==**## ==> spawn ssh root@192.168.2.1
root@192.168.2.1's password:
Last login: Tue Apr 28 16:55:15 2020 from 172.22.0.148
SIOCADDRT: No such process
[root@server2 ~]# /usr/bin/transfer_file send /tmp /root/StorageStressTest.pyc 2 ID.4 root 192.168.3.1 123456 server3 ID.5 root 192.168.4.1 123456 server3 && wait && sync && exit
3. scp to ID.4 192.168.3.1 ##**==++==**## ==> spawn scp -r /tmp/StorageStressTest.pyc root@192.168.3.1:/tmp/
root@192.168.3.1's password:
StorageStressTest.pyc 100% 39KB 38.7KB/s 00:00
3. ssh to ID.4 192.168.3.1 ##**==++==**## ==> spawn ssh root@192.168.3.1
root@192.168.3.1's password:
Last login: Tue Apr 28 16:14:25 2020 from 172.21.35.2
[root@server3 ~]# /usr/bin/transfer_file send /tmp /root/StorageStressTest.pyc 3 ID.5 root 192.168.4.1 123456 server3 && wait && sync && exit
4. scp to ID.5 192.168.4.1 ##**==++==**## ==> spawn scp -r /tmp/StorageStressTest.pyc root@192.168.4.1:/tmp/
StorageStressTest.pyc 100% 39KB 23.3MB/s 00:00
logout
Connection to 192.168.3.1 closed.
logout
Connection to 192.168.2.1 closed.
logout
Connection to 192.168.1.1 closed.
/root/StorageStressTest.pyc
传输到本地(故方式为receive
),命令:multi_scp -t 5 -m receive -f /root/StorageStressTest.pyc
。
命令运行完毕后,文件从远端服务器/root
传输到本地/tmp
下,中间跳转服务器将文件保存在/tmp
本文分享自 WriteSimpleDemo 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!