Python基础 -- 使用Python实现ssh终端并实现数据处理与统计功能

Python 终端自定义统计功能教程

1. 概述

本教程展示了如何使用Python编写一个简单的SSH客户端。该客户端连接到远程服务器,执行命令,并监听远程服务器的输出。本教程使用了paramiko库来处理SSH连接,使用了matplotlib来绘制图表,numpy处理数据,ctypes用于处理无符号64位整数。

2. 主要功能

  • SSH连接 : 使用paramiko库连接到远程服务器。
  • 多线程监听 : 使用Python的threading模块,允许同时监听远程服务器的输出和处理用户输入。
  • 时间戳处理: 解析远程服务器输出中的特定时间戳,并计算发送和接收之间的时间差。
  • 数据可视化 : 使用matplotlib生成并保存时间差的图表。

3. 环境配置

  • 安装依赖库:

    • paramiko: 处理SSH连接。
    • matplotlib: 用于绘制图表。
    • numpy: 用于处理数据。

    通过以下命令安装依赖:

    bash 复制代码
    pip install paramiko matplotlib numpy

4. 代码解释

python 复制代码
import paramiko
import threading
import matplotlib.pyplot as plt
import ctypes
import numpy as np
from datetime import datetime

# 全局列表,用于存储接收到的时间戳
ts_rpmsg_resp = []
ts_rpmsg_send = []

def ssh_connect_and_execute(hostname, port, username, password):
    """
    连接到远程服务器,打开一个交互式Shell会话,并处理远程输出。

    参数:
        hostname (str): 远程服务器的IP地址或主机名。
        port (int): SSH连接使用的端口号。
        username (str): SSH登录的用户名。
        password (str): SSH登录的密码。
    """
    # 创建SSH客户端实例
    ssh = paramiko.SSHClient()
    
    # 将未知主机自动添加到known_hosts文件中
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        # 尝试连接到远程服务器
        ssh.connect(hostname, port, username, password)
        
        # 打开一个交互式的Shell会话,允许执行远程命令
        channel = ssh.invoke_shell()

        def listen_to_remote_output():
            """
            监听远程服务器的输出,处理并提取特定的时间戳数据。
            """
            buffer = ""
            while True:
                # 检查是否有数据可读
                if channel.recv_ready():
                    data = channel.recv(1024).decode('utf-8')  # 接收数据并解码
                    buffer += data
                    
                    # 按行处理接收到的数据
                    while "\n" in buffer:
                        line, buffer = buffer.split("\n", 1)
                        print(line)  # 输出接收到的每行数据
                        
                        # 检测并处理发送时间戳
                        if "set_light_state_rpmsg:366 rpmsg_send start at:" in line:
                            timestamp_str = line.split(':')[-1].strip()
                            timestamp = ctypes.c_uint64(int(timestamp_str)).value
                            ts_rpmsg_send.append(timestamp)
                            print("========== send ===========\n")
                        
                        # 检测并处理接收时间戳
                        if "rpmsg_recv:64 len:32 at:" in line:
                            timestamp_str = line.split(':')[-1].strip()
                            timestamp = ctypes.c_uint64(int(timestamp_str)).value
                            ts_rpmsg_resp.append(timestamp)
                            print("========== resp ===========\n")
                        
                        # 如果接收到超过100个时间戳,绘制时间差图表
                        if len(ts_rpmsg_resp) > 100:
                            array1 = np.array(ts_rpmsg_resp, dtype=np.uint64)
                            array2 = np.array(ts_rpmsg_send, dtype=np.uint64)
                            differences = array1 - array2
                            
                            # 绘制时间差的折线图
                            plt.plot(range(len(differences)), differences, marker='o')
                            plt.xlabel('Index')
                            plt.ylabel('Difference')
                            plt.title('Difference between send and receive timestamps')
                            plt.grid(True)
                            
                            # 保存图像为PNG文件
                            ts_file_name = datetime.now().strftime("%Y%m%d_%H%M%S")
                            filename = f"difference_plot_{ts_file_name}.png"
                            plt.savefig(filename)
                            
                            # 清空时间戳列表,为下一批数据做准备
                            ts_rpmsg_resp.clear()
                            ts_rpmsg_send.clear()

        # 启动一个新线程来监听远程服务器的输出
        threading.Thread(target=listen_to_remote_output, daemon=True).start()

        # 主线程循环,等待用户输入命令
        while True:
            user_input = input("Enter command: ")  # 获取用户输入
            if user_input:  # 如果输入不为空
                channel.send(user_input + "\n")  # 发送命令到远程服务器
                print(f"Sent: {user_input}")

    except Exception as e:
        print(f"SSH connection failed: {e}")  # 捕获并打印任何异常
    finally:
        ssh.close()  # 关闭SSH连接

# 使用示例:使用上述函数连接到指定的SSH服务器
hostname = "192.168.1.26"
port = 22  # SSH默认端口
username = "root"
password = ""

ssh_connect_and_execute(hostname, port, username, password)

5. 使用示例

最后展示了如何调用ssh_connect_and_execute函数来连接到指定的远程服务器。只需提供hostnameportusernamepassword,即可开始与服务器的交互。

6. 扩展与应用

  • 你可以扩展此脚本以处理不同类型的命令和输出。
  • 可以将图表生成的逻辑进一步优化,例如增加数据的存储和分析功能。
相关推荐
oy_mail12 分钟前
QoS质量配置
开发语言·智能路由器·php
oyzz12015 分钟前
PHP操作redis
开发语言·redis·php
nashane33 分钟前
HarmonyOS 6学习:网络能力变化监听与智能提示——告别流量偷跑,打造贴心网络感知应用
开发语言·php·harmony app
Polar__Star1 小时前
如何在 AWS Lambda 中正确使用临时凭证生成 S3 预签名 URL
jvm·数据库·python
凌波粒1 小时前
Java 8 “新”特性详解:Lambda、函数式接口、Stream、Optional 与方法引用
java·开发语言·idea
m0_743623922 小时前
React 自定义 Hook 的命名规范与调用规则详解
jvm·数据库·python
拾贰_C2 小时前
【Google | Gemini | API | POST】怎么使用Google 的Gemini API (原生版)
开发语言·lua
FreakStudio2 小时前
无硬件学LVGL—定时器篇:基于Web模拟器+MicroPython速通GUI开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
gCode Teacher 格码致知3 小时前
Python提高:pytest的简单案例-由Deepseek产生
python·pytest