一、远程执行命令
- 远程执行命令,有两种方式:
- 1、基于ssh_obj 直接连接并执行(内部也是调用transport去连接)
- 2、基于自定义transport
- 远程传输文件,只有一种方式
- 1、基于自定义transport
- 用户名密码(基于 ssh_obj )
-
import paramiko # 实例化出一个ssh对象 ssh_obj = paramiko.SSHClient() ssh_obj.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 允许添加不在konw_hosts中的主机 # 用该对象去连接server并执行命令 ssh_obj.connect(hostname='192.168.10.202', port=22, username='root', password='redhat') stdin, stdout, stderr = ssh_obj.exec_command('df') data = stdout.read().decode() if not data: data = stderr.read().decode() # 因为管道中内容读完就没有了,所以不能用三元运算 print(data) # 关闭连接 ssh_obj.close()
- 用户名密码(自定义transport )
-
import paramiko # 重新给 transport 字段赋值 transport = paramiko.Transport(('192.168.10.202', 22)) transport.connect(username='root', password='redhat') # 更改该 ssh obj对象的_transport字段(创建链接并执行命令) ssh_obj = paramiko.SSHClient() ssh_obj._transport = transport stdin, stdout, stderror = ssh_obj.exec_command('df') data = stdout.read().decode() if not data: data = stderror.read().decode() print(data) transport.close()
- 秘钥(基于ssh_obj):
-
import paramiko import os import sys root = os.path.dirname(os.path.abspath('__file__')) sys.path.append(root) private_key = os.path.join(root, 'id_rsa') # 创建一个ssh 对象, 并执行命令 ssh_obj = paramiko.SSHClient() ssh_obj.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_obj.connect(hostname='192.168.10.202', port=22, username='root', key_filename=private_key) stdin, stdout, stderror = ssh_obj.exec_command('df') data = stdout.read().decode()
ssh_obj.close()
if not data: data = stderror.read().decode() print(data)
- 秘钥(自定义transport)
-
import paramiko import os import sys root = os.path.dirname(os.path.abspath('__file__')) sys.path.append(root) sec_key = paramiko.RSAKey.from_private_key_file(os.path.join(root, 'id_rsa')) # 创建一个transport传输通道, 并指定连接参数 transport = paramiko.Transport(('192.168.10.202', 22)) transport.connect(username='root', pkey=sec_key) # 更改ssh 对象的使用创建的传输通道 ssh_obj = paramiko.SSHClient() ssh_obj._transport = transport # 执行命令,获取结果 stdin, stdout, stderror = ssh_obj.exec_command('ls') data = stdout.read().decode()
transport.close() if not data: data = stderror.read().decode() print(data)
二、传输文件(只能通过transport来进行传输)
- 用户名密码
-
import paramiko # 定义通道,指定连接参数 transport = paramiko.Transport(('192.168.10.202', 22)) transport.connect(username='root', password='redhat') # 创建链接 sftp = paramiko.SFTPClient.from_transport(transport) # 传输文件,文件存在则覆盖,不存在则创建 sftp.put('s1.py', '/usr/local/src/s1.py') # y一定要指定scp过去的文件名称,否则报错 sftp.put('s1.py', '/usr/local/src/test.py') transport.close()
-
import paramiko import os import sys root = os.path.dirname(os.path.abspath('__file__')) sys.path.append(root) sec_key = paramiko.RSAKey.from_private_key_file(os.path.join(root, 'id_rsa')) # 定义通道,指定连接参数 transport = paramiko.Transport(('192.168.10.202', 22)) transport.connect(username='root', pkey=sec_key) # 创建链接 sftp = paramiko.SFTPClient.from_transport(transport) # 传输文件,文件存在则覆盖,不存在则创建 sftp.put('s1.py', '/usr/local/src/qiao1.py') # y一定要指定scp过去的文件名称,否则报错 sftp.put('s1.py', '/usr/local/src/qiao2.py') transport.close()
- 问题:
- 对于执行命令可以使用ssh_obj ,也可以使用transport;但是对于上传文件,只能使用transport
- 那么若需要执行N条命令后再传文件,然后再执行命令,则显然使用ssh_obj 的方式会不断创建链接(从ssh_obj.connect()执行命令到transport.connect()上传文件)
- 即,最好均使用transport,将所有操作定义为一组操作,链接只需要创建一次,在这个链接上完成所有任务