Paramiko使用注意问题

Paramiko官网文档链接: http://docs.paramiko.org/en/stable/

一、执行指令路径

exec_command是在登录时默认路径下执行命令,且每次执行都是在登录时的默认路径下执行命令,即使执行了client.exec_command('cd XXX'),再执行下一条指令时,仍然在登录时的默认路径。

要规避该问题有三种方法

1、每次与路径相关的指令用绝对路径

2、一条字符串包含多条指令,指令间用分号间隔,一起传递。

client.exec_command('cd /home/; ls -al')

3、交互式编程,通过invoke_shell开启一个会话,然后用会话的send,recv方法分别发送和接收指令。

 

二、SFTP传递文件情况实时监测

当SFTP需要发送或接收的文件较大时,传递时间较长,等待过程中需要提示文件传递情况。

注意put方法中的callback,可以定义一个回调函数,以实时检测文件传递情况。

put(localpathremotepathcallback=Noneconfirm=True)

Copy a local file (localpath) to the SFTP server as remotepath. Any exception raised by operations will be passed through. This method is primarily provided as a convenience.

The SFTP operations use pipelining for speed.

Parameters:
  • localpath (str) – the local file to copy
  • remotepath (str) – the destination path on the SFTP server. Note that the filename should be included. Only specifying a directory may result in an error.
  • callback (callable) – optional callback function (form: func(int, int)) that accepts the bytes transferred so far and the total bytes to be transferred
  • confirm (bool) – whether to do a stat() on the file afterwards to confirm the file size
sftp_client.put(src_file, dst_file,callback=self.PutCallback)

回调函数调用的非常频繁,具体时间未测试。为减少提示次数,定义每增加5%提示一次。

def PutCallback(self,TransferredSize, ToBeTransferred):
    rate = int(TransferredSize * 100 / ToBeTransferred)
    if rate > self.percent + 5:
        self.percent = rate
 

三、执行指令持续输出

https://stackoverflow.com/questions/25260088/paramiko-with-continuous-stdout

stdin, stdout, stderr = client.exec_command(str_command)  #str_command为需要执行的指令

for l in self.line_buffered(stdout):  #stdout为持续输出的结果,l为结果的每一行。如果行中包含update_prog_percent则输出给界面显示
    if "update_prog_percent" in l:
        self.MsgSigOut.emit(addr + l, 1)
    self.log.info(addr + l)
def line_buffered(self, f):     #每读取一行执行结果就输出一行
    line_buf = ""
    while not f.channel.exit_status_ready():
        line_buf += f.read(1).decode('utf8')
        if line_buf.endswith('\n'):
            yield line_buf
            line_buf = ''


四、Client、Channel、Transport的关系

SSHClient表示与SSH server会话的高层表示,封装了Transport、Channel和SFTPClient。在SSHClient源代码中可以看到其包含了一个transport作为私有变量,通过transport创建出channel后在channel执行exec_command和invoke_shell。

Transport像一个流而不是像socket,它协商了加密会话,鉴权并创建了流的隧道控制,也即channel。许多的channel通过一个会话复用。(通常在端口转发(port forwarding)模式下)。

端口转发(port forwarding)原理见下文:

https://www.cnblogs.com/kidsitcn/p/11090252.html

一个Channel与一个socket类似,其API与Python socket API完全一致。SSH2有一个类似滑动窗口的流控机制,如果客户端停止从Channel读取,并且Channel的buffer满了,则服务器不能再向客户端发送数据直到客户端读取了数据。(这不会影响同一个transport下面其他channel的流控,同一个transport下面的channel都是独立进行流控的)。类似的,如果服务器不及时读取客户端发送的数据,客户端发送数据将会出现阻塞,除非客户端设置了超时机制。

exec_command在服务器执行命令,如果服务器允许执行,命令执行后channel立即连接到stdin、stdout和stderr。

exec_command命令执行完后,channel会关闭并且不再使用,如果要执行其他命令需要重新打开一个channel。

invoke_shell在channel上获取一个交互式shell会话。如果服务器允许,channel将连接到stdin、stdout和stderr。

在invoke_shell之前一般需要调用get_pty创建伪终端,channel连接到伪终端的stdin、stdout和stderr。

当shell退出时,channel会关闭并且不再被使用。如果想打开领一个shell需要打开一个新的channel。

get_pty从服务器获取一个伪终端,这通常在创建client channel之后,请求服务器为invoke_shell创建的shell提供服务。如果只是通过exec_command执行单个指令则不需要调用该方法。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值