我有脚本 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(终端)有关,但不确定......
任何帮助/指示将不胜感激!
您可以使用管道与子进程进行通信。 在下面的示例中,“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