Python 终端自定义统计功能教程
1. 概述
本教程展示了如何使用Python编写一个简单的SSH客户端。该客户端连接到远程服务器,执行命令,并监听远程服务器的输出。本教程使用了paramiko
库来处理SSH连接,使用了matplotlib
来绘制图表,numpy
处理数据,ctypes
用于处理无符号64位整数。
2. 主要功能
- SSH连接 : 使用
paramiko
库连接到远程服务器。 - 多线程监听 : 使用Python的
threading
模块,允许同时监听远程服务器的输出和处理用户输入。 - 时间戳处理: 解析远程服务器输出中的特定时间戳,并计算发送和接收之间的时间差。
- 数据可视化 : 使用
matplotlib
生成并保存时间差的图表。
3. 环境配置
-
安装依赖库:
paramiko
: 处理SSH连接。matplotlib
: 用于绘制图表。numpy
: 用于处理数据。
通过以下命令安装依赖:
bashpip 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
函数来连接到指定的远程服务器。只需提供hostname
、port
、username
和password
,即可开始与服务器的交互。
6. 扩展与应用
- 你可以扩展此脚本以处理不同类型的命令和输出。
- 可以将图表生成的逻辑进一步优化,例如增加数据的存储和分析功能。