From 4c80e4784df5974037ea4629e1a1e46fe10516ba Mon Sep 17 00:00:00 2001 From: "Peter J. Holzer" Date: Thu, 8 Aug 2019 13:13:13 +0200 Subject: [PATCH] Capture stderr, too --- app.py | 78 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/app.py b/app.py index 87702e0..7cdd0a7 100644 --- a/app.py +++ b/app.py @@ -17,6 +17,7 @@ app.config.from_object(config) class Authenticator(Resource): def post(self): + log.info("received login request %s", request.json) if request.json and request.json.get("token", None) == config.token: session["authorized"] = True log.info("session: %s", session) @@ -39,60 +40,36 @@ class Starter(Resource): if "args" in request.json: args += request.json["args"] log.info("args: %s", args) - proc = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True) - procinfo = { "popen": proc, "pid": proc.pid, "started": time.time(), "stdout": [] } + proc = subprocess.Popen( + args, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True) + procinfo = { "popen": proc, "pid": proc.pid, "started": time.time(), "stdout": [], "stderr": [] } running.append(procinfo) pid = proc.pid log.info("pid: %s", pid) timeout = request.json.get("timeout", 0.0) + log.debug("timeout: %s", timeout) if timeout: - fd = proc.stdout - p = select.poll() - p.register(fd) - t0 = time.time() - t1 = t0 + timeout - while True: - dt = t1 - time.time() - if dt < 0: - break - ready = p.poll(dt * 1000) - log.debug("ready: %s", ready) - if ready: - ln = fd.readline() - log.debug("ln: %s", ln) - if ln == "": - break; - procinfo["stdout"].append(ln) + get_output(procinfo, timeout) try: procinfo["status"] = proc.wait(0.1) for ln in proc.stdout: procinfo["stdout"].append(ln) + for ln in proc.stderr: + procinfo["stderr"].append(ln) procinfo["finished"] = time.time() except subprocess.TimeoutExpired: pass return { x: procinfo[x] - for x in ["pid", "started", "stdout", "status", "finished"] + for x in ["pid", "started", "stdout", "stderr", "status", "finished"] if x in procinfo } class Status(Resource): def get(self, pid): for procinfo in running: if "finished" not in procinfo: - p = select.poll() - p.register(procinfo["popen"].stdout) - t1 = time.time() + 1.0 - while True: - dt = t1 - time.time() - if dt < 0: - break - ready = p.poll(dt * 1000) - log.debug("ready: %s", ready) - if ready: - ln = procinfo["popen"].stdout.readline() - log.debug("ln: %s", ln) - if ln == "": - break; - procinfo["stdout"].append(ln) + get_output(procinfo, 1.0) try: procinfo["status"] = procinfo["popen"].wait(0.1) procinfo["finished"] = time.time() @@ -101,10 +78,39 @@ class Status(Resource): for procinfo in running: if procinfo["pid"] == pid: return { x: procinfo[x] - for x in ["pid", "started", "stdout", "status", "finished"] + for x in ["pid", "started", "stdout", "stderr", "status", "finished"] if x in procinfo } +def get_output(procinfo, timeout): + proc = procinfo["popen"] + p = select.poll() + p.register(proc.stdout) + p.register(proc.stderr) + t0 = time.time() + t1 = t0 + timeout + eof = False + while not eof: + dt = t1 - time.time() + if dt < 0: + break + ready = p.poll(dt * 1000) + log.debug("ready: %s", ready) + for fd in ready: + if fd[0] == proc.stdout.fileno(): + ln = proc.stdout.readline() + log.debug("ln: %s", ln) + if ln == "": + eof = True + continue + procinfo["stdout"].append(ln) + if fd[0] == proc.stderr.fileno(): + ln = proc.stderr.readline() + log.debug("ln: %s", ln) + if ln == "": + eof = True + continue + procinfo["stderr"].append(ln)