You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Subprocess运行Jar的日志发送至Telegram机器人

解决方案

要实现捕获Jar包的实时日志并通过Telegram机器人发送,你需要结合子进程输出捕获和异步任务调度来处理,避免阻塞机器人的事件循环。以下是具体实现步骤:

核心代码实现

import subprocess
import asyncio
import threading
import time

from aiogram import types

# 你已有的日志发送函数(替换123456789为你的实际聊天ID)
async def send_logs(jar_log_text: str):
    await bot.send_message(123456789, jar_log_text)

def handle_subprocess_output(process):
    # 获取主线程的异步事件循环
    loop = asyncio.get_event_loop()
    log_batch = []
    batch_size = 10  # 每攒10条日志发送一次
    last_send_time = time.time()
    timeout = 5  # 5秒内无新日志也发送当前批次

    def send_batch():
        if log_batch:
            batch_content = '\n'.join(log_batch)
            # 将异步任务提交到事件循环执行
            asyncio.run_coroutine_threadsafe(send_logs(batch_content), loop)
            log_batch.clear()

    try:
        # 实时读取子进程输出
        for line in iter(process.stdout.readline, b''):
            line_text = line.decode('utf-8').strip()
            if line_text:
                log_batch.append(line_text)
                current_time = time.time()
                # 达到批次大小或超时则发送
                if len(log_batch) >= batch_size or current_time - last_send_time >= timeout:
                    send_batch()
                    last_send_time = current_time
        # 进程结束后发送剩余日志
        send_batch()
    except Exception as e:
        print(f"日志处理出错: {e}")
    finally:
        process.wait()

def run_jar(java8_path, core_path):
    # 启动Jar包并捕获输出(合并stdout和stderr)
    process = subprocess.Popen(
        [java8_path, '-jar', core_path],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=False
    )
    # 启动单独线程处理日志,避免阻塞机器人的异步循环
    output_thread = threading.Thread(target=handle_subprocess_output, args=(process,))
    output_thread.daemon = True  # 设置为守护线程,随主进程退出
    output_thread.start()

关键细节说明

  • 替换subprocess.call为Popen:
    subprocess.call会阻塞主线程直到Jar包运行结束,无法实时捕获日志。Popen启动子进程在后台运行,允许我们逐行读取输出。

  • 多线程处理:
    读取子进程输出是阻塞操作,放在单独线程中执行可以避免卡住Telegram机器人的异步事件循环(aiogram依赖异步循环处理消息)。

  • 异步任务调度:
    由于send_logs是异步函数,不能直接在同步线程中调用。asyncio.run_coroutine_threadsafe将异步任务提交到已有的事件循环中执行,确保符合aiogram的异步要求。

  • 日志批次发送:
    加入批次发送逻辑是为了避免触发Telegram的消息频率限制。你可以根据需求调整batch_size和timeout参数。

注意事项

  1. 聊天ID: 务必将代码中的123456789替换为你的真实Telegram聊天ID(整数类型,不要带前导零)。
  2. 错误处理: 可以在send_logs函数中添加try-except块,处理消息发送失败的情况(如机器人被拉黑、网络异常)。
  3. 编码问题: 如果Jar包日志使用非UTF-8编码,需要调整line.decode()中的编码格式(如gbk)。

内容的提问来源于stack exchange,提问作者Creeper Hack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:42:42