python之paramiko模块
-
和pexpect模块功能相似,不过更简洁。基于SSH远程登录,默认端口22
-
pip3 install paramiko 第三方模块,提供了SSH远程登录服务器执行命令和下载文件的功能。
-
基于用户名和密码的SSHClient登录
-
AutoAddPolicy:遇到陌生主机,自动把信任主机添加到host_allow列表
-
RejectPolicy:遇到陌生主机直接拒绝
-
WarningPolicy:遇到陌生主机会提示,还是会添加
-
connect(hostname, port, username, password, pkey, key_filename, timeout, allow_agent, look_for_keys, compress, sock, gss_auth,gss_kex, gss_deleg_creds, gss_host, banner_timeout, auth_timeout, gss_trust_dns, passphrase)
-
exec_command(command, bufsize, timeout, get_pty, environment)
-
bufszie 缓冲区大小,默认为-1
-
ssh = paramiko.SSHClient()#实例一个连接对象 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)#设置允许连接陌生主机 ssh.connect(hostname,username,port,password,pkey)#连接被管理机 stdio,stdout,stderr = ssh.exec_command(cmd)#发送命令 print(stdout.read().decode())#获取命令结果 ssh.close()#关闭连接
-
-
基于密钥的SSHClient登录
-
连接端生成私钥和公钥,把公钥给服务器,连接只需私钥免密登录
-
公钥.pub后缀 私钥没后缀
-
-
sudo ssh-keygen -t rsa 创建密钥文件
-
sudo ssh-copy-id -i 文件路径.pub root@xxx.xxx.xxx.xxx 分发公钥到服务器
-
paramiko.RSAKey.from_private_key_file('.ssh/id_rsa',password) 指定本地的RSA私钥文件,默认目录为''.ssh/id_rsa"
-
如果创建密钥文件时设置有密码,就给参数password
-
没设置就免密登录
-
import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy) pkey = paramiko.RSAKey.from_private_key_file('.ssh/id_rsa') ssh.connect(hostname,port,username,pkey) stdio,stdout,stderr = ssh.exec_command(cmd) print(stdout.read(),stderr.read())
-
-
基于Transport用户名和密码登录
-
Transport方式不止执行命令还可以执行下载上传命令
-
Transport(sock, default_window_size, default_max_packet_size, gss_kex, gss_deleg_creds)
import paramiko #基于Transport用户名密码方式登录 tran = paramiko.Transport(('192.168.0.1',22)) tran.connect(username='root',password='123456') #实例一个SSHClient对象 ssh = paramiko.SSHClient() #将SSHClient的对象的transport指定为以上的tran就可以和SSHClient一样执行命令 ssh._transport = tran #执行命令 stdio,stdout,stderr = ssh.exec_command(cmd) print(stdout.read())
-
-
基于Transport的密钥登录
pkey = paramiko.RSAKey.from_prviate_key_file('/.ssh/id_rsa') tran = paramiko.Transport(('192.168.0.1',22)) tran.connect(username,pkey) ssh = paramiko.SSHClient() ssh._transport = tran ssh.exec_command(cmd)
-
Transport对象下载上传文件,SFTPClient方式
-
一个Transport实例相当于创建一个通道进行文件传输
-
SFTPClient.from_transport(t, window_size, max_packet_size) t为创建的实例
-
from paramiko import SFTPClient,Transport def connect_(ip,username,pkey): try: tran = Transport((ip,22)) tran.connect(username,pkey) #把Transport实例通道传进来,指定连接的通道 sftp = SFTPClient.from_transport(tran) except Exception: return None return sftp def upload_file(sftp,localpath,remotepath): #上传文件 sftp.put(localpath,remotepath) def download_file(sftp,localpath,remotepath): #下载文件 sftp.get(localpath,remotepath) def main(): pkey = RSAKey.from_prviate_key_file('/.ssh/id_rsa') sftp = connect_(ip, username, pkey) if sftp: upload_file(sftp, localpath, remotepath) #download_file(sftp, localpath, remotepath) sftp.close() if __name__ == '__main__': main()
-
接受命令的虚拟终端
-
1.开一个socket连接 tran = Transport((ip,port))
-
2.开启一个客户端 tran.start_client()
-
3.登录服务器 tran.auth_password(username, password, event, fallback)
-
4.创建一个会话终端对象 channel = tran.open_session(window_size=None, max_packet_size=None, timeout=None )
-
5.获取终端 channel.get_pty()
-
6.激活终端 channel.invoke_shell()
-
7.发送命令 channel.sendall(cmd)
-
8.获取命令结果 channel.recv(1024)
-
#类似xshell的终端模拟软件,保持一个shell状态 import paramiko import os import sys import select def connect_(username,ip,password): try: tran = paramiko.Transport((ip,22))#建立一个socket通道 tran.start_client() #启动一个客户端 tran.auth_password(username=username, password=password)#用户名和密码登录 channel = tran.open_session()#打开一个会话通道 channel.get_pty()#获取终端 channel.invoke_shell()#激活终端 except paramiko.ssh_exception.SSHException: print('连接错误') return None return channel
# 下面就可以执行你所有的操作,用select实现 # 对输入终端sys.stdin和 通道进行监控, # 当用户在终端输入命令后,将命令交给channel通道,这个时候sys.stdin就发生变化,select就可以感知 # channel的发送命令、获取结果过程其实就是一个socket的发送和接受信息的过程 def main(): username = 'root' ip = '192.168.0.1' password = '123456' channel = connect_(username, ip, password) if channel: while True: readlist,writelist,errlist = select.select([channel,sys.stdin],[],[]) #发送命令 if sys.stdin in readlist: cmd = sys.stdin.read(1) channel.sendall(cmd) #获取命令结果 if channel in readlist: res = channel.recv(1024)#接受结果 if not res:#判断结果是否为空 print('断开连接') break sys.stdout.write(res.decode())#输出到屏幕 sys.stdout.flush()#刷新缓冲区 channel.close() tran.close() if __name__ == '__main__': main()