如何通过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信号转发给前台运行的进程。
修改步骤
- 替换中断信号处理逻辑:当客户端发送"^C"时,直接向PTY写入
chr(3).encode(),而非发送字符串或杀死容器 - 跳过常规输入处理:中断信号不属于用户命令,需跳过
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
相关产品推荐
相关产品推荐

