linux上面写python3日志服务器

一.安装python版本:3.6.8

sudo yum install python3

pip3 install websockets

pip3 install asyncio

安全组 里面任意ip都可以访问 A1:9999 A2:9998两个对外的端口

二.python日志服务器代码:监听客户端websocket

import asyncio

import websockets

import os

import traceback

import sys

import locale

from datetime import datetime

尝试修复终端编码

def fix_encoding():

"""尝试修复终端编码问题"""

try:

获取当前编码

current_encoding = locale.getpreferredencoding()

print(f"Current encoding: {current_encoding}")

如果是Windows,尝试设置UTF-8

if sys.platform == "win32":

os.system("chcp 65001 > nul")

设置环境变量

os.environ'PYTHONIOENCODING' = 'utf-8'

尝试重新设置标准输出编码

if sys.stdout.encoding != 'UTF-8':

import io

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')

sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')

except Exception as e:

print(f"Warning: Could not fix encoding: {e}")

在main函数开始前调用

fix_encoding()

然后继续你的代码...

open_files = {}

def get_open_file(filename):

"""获取或创建日志文件,确保目录存在"""

log_dir = os.path.dirname(filename)

if log_dir and not os.path.exists(log_dir):

try:

os.makedirs(log_dir, exist_ok=True)

except OSError as e:

print(f"创建日志目录失败: {e}")

return None

if filename in open_files:

return open_filesfilename

else:

try:

open_file = open(filename, 'a', encoding='utf-8')

open_filesfilename = open_file

return open_file

except IOError as e:

print(f"打开日志文件失败: {e}")

return None

def close_open_file(filename):

"""安全关闭日志文件并从缓存中移除"""

if filename in open_files:

try:

open_filesfilename.close()

except IOError as e:

print(f"关闭日志文件失败: {e}")

finally:

del open_filesfilename

async def echo(websocket, path):

"""处理WebSocket连接"""

client_ip = websocket.remote_address0 if websocket.remote_address else "unknown"

print(f"\n=== 新的客户端连接 ===")

print(f"--IP: {client_ip}")

print(f"--path: {path}")

接收客户端发送的文件名前缀(首次消息)

try:

增加超时时间为10秒

print("等待客户端发送前缀信息...")

path_data = await asyncio.wait_for(websocket.recv(), timeout=10.0)

print(f" 收到数据: {repr(path_data)}")

print(f" 数据类型: {type(path_data)}")

print(f" 数据长度: {len(path_data)}")

净化输入,确保文件名安全

path_suffix = path_data.strip()

print(f"--原始前缀: {path_suffix}")

只保留字母、数字、下划线和横线(避免路径注入)

path_suffix = "".join(c for c in path_suffix if c.isalnum() or c in \['_', '-'])

如果净化后为空,使用默认值

if not path_suffix:

path_suffix = "default"

print("前缀为空,使用默认值")

print(f"最终使用的前缀: {path_suffix}")

except asyncio.TimeoutError:

print("等待前缀超时")

path_suffix = "default"

except websockets.exceptions.ConnectionClosed as e:

print(f"连接已关闭: {e.code} - {e.reason}")

return

except Exception as e:

print(f"接收前缀时发生异常: {e}")

traceback.print_exc()

return

生成精确到毫秒的时间戳(格式:年-月-日-时-分-秒-毫秒)

timestr = datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f"):-3

构建日志文件名(格式:log/前缀-时间戳.txt)

file_name = f"tinyou2log/{path_suffix}-{timestr}.txt"

print(f"日志文件: {file_name}")

log_file = get_open_file(file_name)

if not log_file:

print("错误: 无法创建日志文件,连接将关闭")

return

try:

记录连接信息

connect_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"):-3

log_file.write(f"{connect_time} 客户端 {client_ip} 已连接\n")

log_file.write(f"{connect_time} 使用前缀: {path_suffix}\n")

log_file.flush()

接收并记录后续消息

print("等待接收后续消息...")

try:

while True:

message = await websocket.recv()

timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"):-3

log_entry = f"{timestamp} 收到消息: {message}\n"

print(f"收到消息: {message}")

log_file.write(log_entry)

log_file.flush()

except websockets.exceptions.ConnectionClosed:

print("客户端断开连接")

except websockets.exceptions.ConnectionClosedError:

disconnect_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"):-3

print(f"客户端 {client_ip} 断开连接")

log_file.write(f"{disconnect_time} 客户端 {client_ip} 已断开连接\n")

log_file.flush()

except Exception as e:

print(f"处理客户端时发生错误: {e}")

traceback.print_exc()

finally:

close_open_file(file_name)

print(f"日志文件 {file_name} 已关闭")

print("=== 连接处理结束 ===\n")

async def main():

try:

创建日志目录

os.makedirs("tinyou2log", exist_ok=True)

async with websockets.serve(echo, "0.0.0.0", 9998):

print("=" * 60)

print(" WebSocket 日志服务器启动")

print(" 监听地址: 0.0.0.0:9998")

print(" 日志路径: " + os.path.abspath("tinyou2log"))

print(" 等待客户端连接...")

print("=" * 60)

await asyncio.Future() # 保持服务器运行

except OSError as e:

print(f"服务器启动失败: {e}")

if e.errno == 98:

print("端口9999已被占用,请使用其他端口或停止占用该端口的进程")

if name == "main":

loop = asyncio.get_event_loop()

try:

loop.run_until_complete(main())

except KeyboardInterrupt:

print("\n服务器已停止")

finally:

loop.close()

三.客户端测试

测试1:ws://123.56.30.115:9998

测试2:wss://jhtg.ser01.tjxzhd.com/wstyjh2

<!DOCTYPE html>

<html>

<head>

<title>WebSocket测试</title>

<meta charset="utf-8">

</head>

<body>

<h1>WebSocket连接测试</h1>

<div>

<label>服务器地址:</label>

<input type="text" id="serverUrl" value="wss://jhtg.ser01.tjxzhd.com/wstyjh2" style="width: 400px;">

<button onclick="connect()">连接</button>

<button onclick="disconnect()">断开</button>

<button onclick="sendTest()">发送测试消息</button>

</div>

<div>

<label>消息:</label>

<input type="text" id="message" value="test123456" style="width: 300px;">

<button onclick="sendMessage()">发送</button>

</div>

<div>

<h3>日志:</h3>

<pre id="log" style="border: 1px solid #ccc; padding: 10px; height: 300px; overflow: auto;"></pre>

</div>

<script>

let ws = null;

const log = document.getElementById('log');

function addLog(msg) {

const time = new Date().toLocaleTimeString();

log.textContent += `${time} ${msg}\n`;

log.scrollTop = log.scrollHeight;

}

function connect() {

const url = document.getElementById('serverUrl').value;

addLog(`尝试连接到: ${url}`);

ws = new WebSocket(url);

ws.onopen = function(event) {

addLog('连接成功!');

addLog(`readyState: ${ws.readyState}`);

// 立即发送测试消息

ws.send('gandecheng');

};

ws.onmessage = function(event) {

addLog(`收到消息: ${event.data}`);

};

ws.onerror = function(error) {

addLog(`连接错误: ${error}`);

console.error('WebSocket错误:', error);

};

ws.onclose = function(event) {

addLog(`连接关闭 - 代码: {event.code}, 原因: {event.reason}`);

};

}

function disconnect() {

if (ws) {

ws.close(1000, '用户手动断开');

addLog('正在断开连接...');

}

}

function sendMessage() {

if (ws && ws.readyState === WebSocket.OPEN) {

const msg = document.getElementById('message').value;

ws.send(msg);

addLog(`发送: ${msg}`);

} else {

addLog('连接未就绪,无法发送消息');

}

}

function sendTest() {

const testMsg = JSON.stringify({

type: 'test',

timestamp: new Date().toISOString(),

data: '这是一个测试消息'

});

if (ws && ws.readyState === WebSocket.OPEN) {

ws.send(testMsg);

addLog(`发送测试消息: ${testMsg}`);

} else {

addLog('连接未就绪');

}

}

// 页面加载时自动连接

window.onload = function() {

addLog('页面加载完成');

// 可选:自动连接

// connect();

};

</script>

</body>

</html>

相关推荐
@兽血沸腾8 小时前
Windows系统安装Jenkins部署应用至远程Windows服务器操作指南
运维·服务器·jenkins
且从容.11 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道11 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
讯捷蓝达13 小时前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
且从容.14 小时前
ubuntu安装flink
linux·ubuntu·flink
数字新视界15 小时前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
爱和冰阔落15 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨15 小时前
WSL2的安装与使用
linux·wsl
微小的鱼16 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng16 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器