用python实现远程复制 (scp + expect )

本文介绍了一种利用Expect脚本解决SCP文件传输过程中需要手动输入密码的问题,并针对大文件传输时出现的超时问题提供了具体的解决方案。

scp 功能很强大,但需要人工输入 password, 当然可以通过把 公钥保存在远程主机的 ~/.ssh 目录中,而后就不用输入password,但这需要配置.

用 sshpass 可能在命令输入 password, 但 需要用 “sudo apt-get install sshpass” 安装

如果不想用上面两种方法,可以用 expect 编写脚本可以帮助我们自动交互

虽然 python 也提供 pexpect  模块,但既然 expect 很简单,为何不直接用 os.system() 去执行呢?

下面是我编写的类,实现了远程复制 

class RemoteShell:

    def __init__(self, host, user, pwd):
        self.host = host
        self.user  = user
        self.pwd  = pwd


    def put(self, local_path, remote_path):
scp_put = '''
spawn scp %s %s@%s:%s
expect "(yes/no)?" {
send "yes\r"
expect "password:"
send "%s\r"
} "password:" {send "%s\r"}
expect eof
exit'''
        os.system("echo '%s' > scp_put.cmd" % (scp_put % (os.path.expanduser(local_path), self.user, self.host, remote_path, self.pwd, self.pwd)))
        os.system('expect scp_put.cmd')
        os.system('rm scp_put.cmd')

但发现每次文件都没有复制完,我想看expect 究竟做了什么事情,还好 expect 提供 -d 参数给出更多的信息。

最后发现是被复制文件太大,expect 超时退出了

在脚本前加入 “set timeout -1" 就OK了


scp_put = '''
set timeout -1
spawn scp %s %s@%s:%s
expect "(yes/no)?" {
send "yes\r"
expect "password:"
send "%s\r"
} "password:" {send "%s\r"}
expect eof
exit'''

总结

1) expect 每一条语句都是顺序执行

 因为scp 可能先返回 (yes/no)? 再 返回 password:, 也可能直接返回password:, 考虑顺序关系,上面语句的层次关系其实如下:
expect "(yes/no)?" {   send "yes\r"
                       expect "password:"
                       send "%s\r"
                    } 
       "password:" {send "%s\r"}

2) 每当 spawn 的程序有输出的时候的,expect都会去匹配, 如果匹配不上,就等下次有输出,再次执行当前的 expect, 直到超时 (我用 expect -d 去追踪,得到的结论);当然可以设置没有超时 "set timeout -1"


3) 如果  expect 退出, 被它 spawn 的程序会被 kill 掉


4) spawn 结束的时候,它向标准输出的的 eof 会被 expect 检测到,正好作为 expect 脚本退出的时机。

对于 scp 可以先检测 100%,因为 scp 会输出复制进度,再检测 eof

expect "100%%"
expect eof


5) expect 是部分匹配,所以不要担心自己不知道程序的完整输出

在系统管理和网络编程中,自动执行远程文件夹的递归拷贝是一项常见任务。使用Python结合Expect模块可以实现这一目标。Expect模块能够模拟人类用户的行为,进行交互式命令的自动输入,这对于需要输入密码或确认的SCP命令尤为有用。首先,你需要在你的Python脚本中导入subprocess模块,因为我们将使用它来调用scp命令。接下来,可以使用Expect模块来处理密码输入和交互过程。具体来说,你可以设置一个超时时间,然后用spawn命令启动scp命令,使用expect来匹配密码提示并发送密码。为了实现递归拷贝,需要在scp命令中使用-r选项。以下是一个简单的代码示例,展示了如何实现这一功能:(代码示例及详细解释,此处略)在这个示例中,我们定义了一个函数`scp_folder_to_remote`,它接受本地路径、远程用户、IP地址、远程路径、密码和端口号作为参数。函数内部构建了一个scp命令,该命令使用Expect模块来自动处理密码输入,并递归地拷贝文件夹到远程主机。这种方法不仅自动化程度高,而且可以大大减少网络编程中重复的手动操作。如果你希望进一步提高你在这方面的技能,可以深入学习《使用PythonExpect实现SCP命令远程拷贝文件文件夹》这份资料,它将为你提供更多实用的技术细节和高级应用场景。 参考资源链接:[使用PythonExpect实现SCP命令远程拷贝文件文件夹](https://wenku.youkuaiyun.com/doc/645cd51895996c03ac3f866c?spm=1055.2569.3001.10343)
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值