键盘中断在子进程内运行的 Docker 容器进程

问题描述 投票:0回答:1

我目前正在构建一个将 Docker 容器连接到 websocket 的系统,然后客户端可以通过 websocket 与该容器交互。我想让客户端能够使用键盘中断来中断 Docker 容器内运行的进程。

到目前为止我的尝试如下:


.........

pty, tty = pypty.openpty()

async def interact_docker(pty, websocket):
    while True:
        data = os.read(pty, 10240)
        print(data)
            # using python's pty as I/O, everytime client gives an input, 
            # the pty reflects this input and duplicates the input into the output. 
            # ex: command "ls" inputted by client will output "ls\r\n" and the result of "ls".
            # to prevent duplicated output from input, save the length of the input string 
            # and add 2 to account for \r\n. Then, for each output from pty, check the first
            # (len(input) + 2) string, and check if the string ends in \r\n. If it does, it means
            # the output is a duplicate of the input, so emit this duplicate.
        check_duplicate = data[:offset]
        if check_duplicate[(offset - 2):] == "\r\n".encode():
            data = data[offset:]

        try:
            await websocket.send_text(data.decode())
        except UnicodeDecodeError:
            print("decoding error")
            await websocket.send_text(data.decode("latin-1"))

container = subprocess.Popen(['docker', 'run', '--name', str(instance.id), '-it', '--rm', '--privileged', '-e', 'DISPLAY', '-v', '/tmp/.X11-unix:/tmp/.X11-unix', '-v', '/lib/modules:/lib/modules', 'iwaseyusuke/mininet'], stdin=tty, stdout=tty, stderr=tty)

loop = asyncio.get_running_loop()
loop.run_in_executor(None, lambda: asyncio.run(interact_docker(pty, websocket)))   
    
while True:
    data = await websocket.receive_text()
    if data == "^C":
        print("keyboard interrupt")
        container.send_signal(signal.SIGINT)
    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())

为了清晰起见,省略了一些代码行,但脚本的主要思想就在那里。目前,使用

container.send_signal(signal.SIGINT)
的尝试只会杀死容器。向 pty 发送“^C”不会向容器内的进程发送 SIGINT,而只是发送文字字符串。

python docker subprocess interrupt pty
1个回答
0
投票

如果您以某种方式在容器内运行服务器,请向该服务器发送特定消息,并在服务器端添加代码以触发 SIGINT。


如果您想向容器内的进程发送信号,请使用

docker exec
:

docker exec <container_name> kill -INT [pid]

如果该进程是容器的主进程,则它的 pid 为 1:

# don't run this at home ;)
docker exec <container_name> kill -INT 1
© www.soinside.com 2019 - 2024. All rights reserved.