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

如何通过WebSocket向Docker容器内进程发送键盘中断信号

如何向Docker容器内的进程发送Ctrl+C中断信号(WebSocket+PTY场景)

问题背景

我正在构建一套Docker容器与WebSocket对接的系统,客户端通过WebSocket与容器bash交互,可执行ls -al等命令并获取结果。但遇到核心问题:运行ping这类持续进程时,客户端无法通过Ctrl+C中断进程,只能陷入输出循环。

当前实现的问题点:

  • 使用container.send_signal(signal.SIGINT)会直接杀死整个容器,而非仅中断当前进程
  • 向PTY发送字符串"^C"只会传递字面内容,无法触发真正的键盘中断

解决方案

核心是向PTY发送Ctrl+C对应的ASCII控制字符(ASCII码0x03,即chr(3)),模拟终端的键盘中断操作,让容器内的bash将SIGINT信号转发给前台运行的进程。

修改步骤

  1. 替换中断信号处理逻辑:当客户端发送"^C"时,直接向PTY写入chr(3).encode(),而非发送字符串或杀死容器
  2. 跳过常规输入处理:中断信号不属于用户命令,需跳过offset更新和后续的常规输入写入逻辑,避免干扰输入去重机制

修改后的核心代码片段

while True:
    data = await websocket.receive_text()
    if data == "^C":
        print("keyboard interrupt")
        # 发送真正的Ctrl+C控制字符(ASCII 0x03)
        os.write(pty, chr(3).encode())
        # 跳过后续输入处理,避免offset错误更新
        continue
    correct_inp = process_input(db, instance, data, expected_inp)
    if correct_inp and len(expected_inp) == 0 and not finished_lab:
        message = "\x1b[1;92m \nSelamat! Anda telah menyelesaikan lab ini.\nAnda bisa melanjutkan penggunaan lab atau anda bisa kembali ke menu utama untuk menghentikan pengerjaan lab. \x1b[0m\n\n"
        await websocket.send_text(message)
        user.finished_labs.append(lab)
        db.commit()
    offset = len(data) + 2    
    data = data + "\n"
    os.write(pty, data.encode())

原理说明

PTY终端会将ASCII 0x03字符识别为中断信号,容器内的bash作为PTY的前台进程,会自动将SIGINT信号转发给当前运行的前台子进程(如ping),从而终止目标进程但保持bash和容器本身正常运行。

内容的提问来源于stack exchange,提问作者Farel Musyaffa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:24:56