访问由另一个脚本启动的子进程

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

我有脚本 1(容器入口点)。脚本 1 使用 Popen 启动一个子进程。这是“等待”此过程以接收来自控制台的实时输入命令并保持服务器运行。

    game_server = await asyncio.create_subprocess_exec(*run_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, stdin=asyncio.subprocess.PIPE)
    async for startup_out_line in game_server.stdout:
        console_print(startup_out_line.decode())
        if server_start_string in startup_out_line.decode('utf-8', 'replace'):
            print("Server Started")
            break

    async with asyncio.TaskGroup() as tg:
        in_task = tg.create_task(running_server_inpipe(game_server))
        out_task = tg.create_task(running_server_outpipe(game_server))
        err_task = tg.create_task(running_server_errpipe(game_server))
        retcode = await game_server.wait()
        if retcode == 0:
            print("Server exited normally")
        else:
            print(f"Error: server exited with code {retcode}")
        in_task.cancel()
        out_task.cancel()
        err_task.cancel()
        
    sys.exit(0 if retcode == 0 else 1)

async def running_server_inpipe(game_server: asyncio.subprocess.Process):
    while True:
        line = await aioconsole.ainput("Enter Command: ")
        game_server.stdin.write(line.encode('utf-8') + b"\n")
        await game_server.stdin.drain()
        console_print("INPIPE - Command Sent: " + line)

async def running_server_outpipe(game_server: asyncio.subprocess.Process):
    async for out_line in game_server.stdout:
        console_print("OUTPIPE - Server Says: " + out_line.decode('utf-8', 'replace'))

async def running_server_errpipe(game_server: asyncio.subprocess.Process):
    async for err_line in game_server.stderr:
        console_print("ERRORPIPE - Server Error: " + err_line.decode('utf-8', 'replace'))

然后我有脚本 2(API),它从外部源接收命令,并尝试访问由脚本 1 启动的子进程,并向其标准输入写入命令。

@API1.route('/quit', methods=['POST'])
def receive_quit_data():
    data = request.get_json()
    try:
        server = data['server']
    except KeyError:
        return jsonify({'status': 'No Server Provided'})
    engage_container = ["docker", "attach", f"{server}"]
    container_process = subprocess.Popen(engage_container, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, text=True)
    container_process.communicate(input="quit\n")
    container_process.wait()
    if container_process.return_code == 0:
        return jsonify({'status': 'Command Sent'})
    return jsonify({'status': 'Command Failed'})

虽然我从 API 得到了 200code。子进程根本不响应这些命令。如果我直接登录终端并写入:

docker attach <SERVERNAME>

然后

save\n

它按预期响应,所以我知道脚本 1 工作正常! 我认为这可能与 PTY(终端)有关,但不确定......

任何帮助/指示将不胜感激!

python docker subprocess
1个回答
0
投票

您可以使用管道与子进程进行通信。 在下面的示例中,“cat”启动,您在终端中编写的所有内容都将发送到子进程标准输入。然后从子进程中获取数据并在终端中打印:

import subprocess
import select
import sys, os
import fcntl

process = subprocess.Popen(
    ["cat"],
    stdin=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    stdout=subprocess.PIPE,
    shell=False,
    bufsize=0,
    pipesize=0
)
fcntl.fcntl(process.stdout, fcntl.F_SETFL, os.O_NONBLOCK)

while process.poll() is None:
    readable, _, _ = select.select([process.stdout, sys.stdin], [], [], 0)
    while readable:
        p = readable.pop()
        if p == process.stdout:  # read from process stdin pipe
            sys.stdout.write(process.stdout.read().decode())
            sys.stdout.flush()
        elif p == sys.stdin:
            # read from pythons app stdin. Send it to process as command
            d = sys.stdin.readline().encode()
            process.stdin.write(d)  # send to the process
© www.soinside.com 2019 - 2024. All rights reserved.