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. 扩展与应用

  • 你可以扩展此脚本以处理不同类型的命令和输出。
  • 可以将图表生成的逻辑进一步优化,例如增加数据的存储和分析功能。
相关推荐
iCxhust17 分钟前
Prj10--8088单板机C语言8259测试(1)
c语言·开发语言
крон3 小时前
【Auto.js例程】华为备忘录导出到其他手机
开发语言·javascript·智能手机
zh_xuan4 小时前
c++ 单例模式
开发语言·c++·单例模式
老胖闲聊4 小时前
Python Copilot【代码辅助工具】 简介
开发语言·python·copilot
Blossom.1184 小时前
使用Python和Scikit-Learn实现机器学习模型调优
开发语言·人工智能·python·深度学习·目标检测·机器学习·scikit-learn
曹勖之5 小时前
基于ROS2,撰写python脚本,根据给定的舵-桨动力学模型实现动力学更新
开发语言·python·机器人·ros2
豆沙沙包?5 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
军训猫猫头6 小时前
96.如何使用C#实现串口发送? C#例子
开发语言·c#
lyaihao6 小时前
使用python实现奔跑的线条效果
python·绘图
liuyang-neu6 小时前
java内存模型JMM
java·开发语言