最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

全球新资讯:Paramiko_Linux

来源:博客园
目录
  • Paramiko
  • SSH
    • 第一版
    • 第二版
    • 最终版
  • SFTP
    • 第一版
    • 第二版

Paramiko

Paramiko官网

从官方的介绍当中我们起码得知以下几个信息:


(资料图片仅供参考)

  1. 此模块用于python3.6以上,目前python3.11左右,完全满足;
  2. 此模块用于实现sshv2协议的客户端和服务端;
  3. 核心类有五种,我们常用的是Clienttt SFTP两个类

SSH

接下来,我们通过paramiko实现通过sshv2连接服务器,并执行ip addr show然后从结果当中把IP地址通过python字符串切割的方式获取到。

实验环境:

  • 服务端:192.168.80.130:kali linux
  • 客户端:windows pycharm
# 服务端基本配置┌──(root㉿kali)-[~/Desktop]└─# systemctl enable --now  sshroot㉿kali)-[~/Desktop]└─# ss -tnlp | grep 22         LISTEN 0      128          0.0.0.0:22        0.0.0.0:*    users:(("sshd",pid=1938,fd=3))LISTEN 0      128             [::]:22           [::]:*    users:(("sshd",pid=1938,fd=4))┌──(root㉿kali)-[~/Desktop]└─# grep -i "permitrootlogin" /etc/ssh/sshd_config PermitRootLogin yes┌──(root㉿kali)-[~/Desktop]└─# systemctl restart ssh    ┌──(root㉿kali)-[~/Desktop]└─# passwd        New password: cba-123Retype new password: cba-123passwd: password updated successfully
┌──(root㉿kali)-[~/Desktop]└─# ip addr show eth0 | sed -n 3p | awk -F" " "{print $2}" | awk -F"/" "{print $1}"192.168.3.19                                                                                                                  ┌──(root㉿kali)-[~/Desktop]└─# hostname -I192.168.3.19 

在使用paramiko的过程当中我们可以选择通过shell命令进行切割字符串,也可以通过python进行切割,由于shelle命令只能在LINUX上执行,如果我们操作是网络设备那shell的命令不再好用了,所以我们打算使用python关于字符串的切割逻辑。

第一版

要求1:要求向linux发送一个df命令,并取回df的其结果。

要求2:要求向linux发送四个命令,并取会其结果

# 要求1import paramiko,timeport_number = 22username = "root"password = "cba-123"ip= "192.168.80.130"# 调用paramiko的sshclient类进行实例化ssh = paramiko.SSHClient()# 斩断ssh进程与文件系统之间的联系ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())# 这一步如果抓包去看的话,其实就是sshv2的连接过程# tcp三次握手、协商版本、交换密钥……、完事后直接四次挥手并不保持连接直接挥手ssh.connect(    port=port_number,    username=username,    password=password,    hostname=ip)# 向ssh发送一个df命令,然后通过标准的输入、输出和错误接收# 打印标准输出stdin, stdout, stderr = ssh.exec_command("df")out = stdout.read()print(out.decode())# 如果不带close最后的中断直接是reset,而使用了close之后最后中断就是平滑的三次握手ssh.close()"C:\Program Files\Python311\python.exe" G:\python2\第十章\test.py Filesystem     1K-blocks     Used Available Use% Mounted onudev             1955888        0   1955888   0% /devtmpfs             398824     1380    397444   1% /run/dev/sda1      101639152 12773768  83656196  14% /tmpfs            1994112        0   1994112   0% /dev/shmtmpfs               5120        0      5120   0% /run/locktmpfs             398820       88    398732   1% /run/user/0
# 要求2的完成可以采取一个非常取巧的办法,把四个命令写到一块即可,如下所示:stdin, stdout, stderr = ssh.exec_command("hostname;df;ps aux|grep ssh;cat /etc/issue")

第二版

要求把上述代码写成函数,并连续执行四个命令,如下所示:

import paramiko, timeport_number = 22username = "root"password = "cba-123"ip = "192.168.3.19"def ssh(cmd):    ssh = paramiko.SSHClient()    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())    ssh.connect(        port=port_number,        username=username,        password=password,        hostname=ip    )    stdin, stdout, stderr = ssh.exec_command(cmd)    out = stdout.read()    print(out.decode())    ssh.close()ssh("df | head -1")ssh("hostname")ssh("cat /etc/issue")ssh("cat /etc/passwd | head -1")

其实像上图这么做是一个循环的过程,是完全的单线程操作,每一个命令都需要完成ssh的过程然后执行命令最后断开连接,这个过程要重复四次,这是特别浪费资源的,但我们在这里不去讨论多线程之类的,也不去关注性能,反正这么就完成任务;

其实代码还可以更简单一点,那就是把命令写在列表,然后循环列表,执行函数;

cmds = ["df|head -1","hostname","whoami","echo $PATH"]for cmd in cmds:    ssh(cmd)

上述代码还有改进的地方,那就是在标准输入和输出那个地方,咱们可以使用三元运算:

stdin, stdout, stderr = ssh.exec_command(cmd)res,err = stdout.read(),stderr.read()result = res if res else errprint(result.decode())ssh.close()

最终版

import paramiko, timeport_number = 22username = "root"password = "cba-123"ip = "192.168.3.19"def ssh(cmd):    ssh = paramiko.SSHClient()    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())    ssh.connect(        port=port_number,        username=username,        password=password,        hostname=ip    )    stdin, stdout, stderr = ssh.exec_command(cmd)    res,err = stdout.read(),stderr.read()    result = res if res else err    print(result.decode())    ssh.close()cmds = ["df|head -1","hostname","whoami","ecdho $PATH"]for cmd in cmds:    ssh(cmd)        "C:\Program Files\Python311\python.exe" G:\python2\第十章\test.py Filesystem     1K-blocks     Used Available Use% Mounted onkalirootzsh:1: command not found: ecdho

SFTP

SFTP是在ssh建立连接的基础上,所以上述代码建立连接的部分,可以直接直接抄下来

第一版

将服务器的/etc/passwd文件下载到本地,命名为backup_hostname

# 将服务器的/etc/passwd文件下载到本地,命名为backup_hostnameimport paramiko, timeport_number = 22username = "root"password = "cba-123"ip = "192.168.3.19"ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect(    port=port_number,    username=username,    password=password,    hostname=ip)# 在ssh的基础上附加或打开sftpsftp = ssh.open_sftp()sftp.get("/etc/hostname","backup_hostname")ssh.close()

第二版

将服务器的/etc下的passwd文件、fstab文件、issue文件全都下载下来;

# 下载import os.pathimport paramikodef sftp_get(file_path):    port_number = 22    username = "root"    password = "cba-123"    ip = "192.168.3.19"    ssh = paramiko.SSHClient()    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())    ssh.connect(        port=port_number,        username=username,        password=password,        hostname=ip    )    # 在ssh的基础上附加或打开sftp    sftp = ssh.open_sftp()    file_in = file_path    file_out = os.path.basename(file_in)    sftp.get(file_in, file_out)    ssh.close()files = ["/etc/passwd","/etc/issue","/etc/hostname"]for file in files:    sftp_get(file)

多次执行会直接进行覆盖的。

这里面涉及到一个新的知识点,那就是取文件的基名,要通过os模块,非常容易理解。

# 上传import os.pathimport paramikodef sftp_put(put_file):    port_number = 22    username = "root"    password = "cba-123"    ip = "192.168.3.19"    ssh = paramiko.SSHClient()    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())    ssh.connect(        port=port_number,        username=username,        password=password,        hostname=ip    )    # 在ssh的基础上附加或打开sftp    sftp = ssh.open_sftp()    file_in = put_file    file_out = f"/tmp/{file_in}.back"    sftp.put(file_in,file_out)    ssh.close()files = ["passwd","issue","hostname"]for file in files:    sftp_put(file)

关键词: