0

I want to utilize subprocess Popen to call strace on Linux. I also want to catch every line of output strace gives, in realtime if possible.

I came up with the following code for that, but for some reason I can't get it working. I'll only get the output AFTER I terminate the program.

from threading import Thread
from queue import Queue, Empty

pid = 1

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()

p = Popen(["strace", "-p", pid], stdout=subprocess.PIPE, bufsize=1)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # thread dies with the program
t.start()

try:
    line = q.get_nowait()
    print("Got it! "+line)
except Empty:
    pass
Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
Druckermann
  • 681
  • 2
  • 11
  • 31
  • Wouldn't you be better with installing signals, as in https://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application ? – Demi-Lune Feb 09 '19 at 17:53
  • Hi! I don't want to trace a Python programm, so there is no use for installing signals, isn't it? – Druckermann Feb 09 '19 at 20:39
  • What is the intended purpose of the Queue? You could directly read from the subprocess output. – VPfB Feb 09 '19 at 20:42
  • The Queue was meant to read the output from a separate thread as a kind of buffer. I tried it without the queue too, but that didn't work either. – Druckermann Feb 09 '19 at 20:47

1 Answers1

1

Here is a short working example:

Please note that:

  • strace writes to stderr (unless -o filename is given)
  • all arguments must be strings (or bytes), i.e. pid must be given as "1"
  • line buffering works only with universal newlines
  • you must be root to trace process 1

import subprocess

PID = 1 

p = subprocess.Popen(
    ["strace", "-p", str(PID)],
    stdin=subprocess.DEVNULL, stderr=subprocess.PIPE,
    universal_newlines=True, bufsize=1)
for line in p.stderr:
    line = line.rstrip()
    print(line)
VPfB
  • 14,927
  • 6
  • 41
  • 75