1

我想捕获命令行程序(即 GDB,但为了简单起见目前已更改为lscat)的所有输入和输出,并将其重定向到文件中,以供以后分析。

我无法接近工作,但我不明白出了什么问题。这是我的最后一次尝试:

#!/usr/bin/env python2

import subprocess
import sys
import select
import os

def get_pipe():
  fd_r, fd_w = os.pipe()
  return os.fdopen(fd_r, "r"), os.fdopen(fd_w, "w")

out_r, out_w = get_pipe()
err_r, err_w = get_pipe()
in_r, in_w = get_pipe()

proc = subprocess.Popen(["ls"] + sys.argv[1:], stdin=in_r, stdout=out_w, stderr=err_w)

out_w.close()
err_w.close()
in_r.close()

running = True
while running:
  input_lst, output_lst, x_lst = select.select([sys.stdin],[out_r, err_r],  [], 0.5)

  if out_r in output_lst+input_lst:
    data = out_r.readlines()
    print "*",data,"*"
  if err_r in output_lst+input_lst:
    data = err_r.readlines()
    print "+",data,"+"
  if sys.stdin in input_lst:
    data = sys.stdin.readline()
    print "-", data, "-"
    in_w.write(data)

  # don't try to quit if we received some data
  if len(input_lst+output_lst+x_lst) != 0:
    continue
  retcode = proc.poll()
  if retcode is not None:
    running = False

out_r.close()
err_r.close()
in_w.close
exit(retcode)

我尝试了其他几个选项,例如 - 编写一个文件包装器,它应该将所有写入 stdin / 从 stdout-err 读取的内容写入外部文件 - 命名管道 - ...

但我得到的最好的是“ls”的第一行。

而且GDB依赖于readlineCLI版,感觉透明抓起来没那么容易!

4

1 回答 1

1

所以经过一段时间的研究,我找到了解决这个问题的方法:

对于non blocking读取和写入,我们只需要等待输入文件用完数据(并抛出异常),然后对输出(stdout 和 stderr)进行相同的操作:

#!/usr/bin/python2

import sys, os
import subprocess
import fcntl

dump = open("/tmp/dump", "w")
dump.write("### starting %s ###" % " ".join(sys.argv))

proc = subprocess.Popen(["<real app>"] + sys.argv[1:], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def nonblocking(fd):
  fl = fcntl.fcntl(fd, fcntl.F_GETFL)
  fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

nonblocking(proc.stdin)
nonblocking(proc.stdout)
nonblocking(proc.stderr)

nonblocking(sys.__stdin__)
nonblocking(sys.__stdout__)
nonblocking(sys.__stderr__)

def me_to_proc():
  x_to_y(sys.__stdin__, proc.stdin, "~in> ")

def proc_to_me():
  x_to_y(proc.stdout, sys.__stdout__, "<out~ ")

def proc_to_me_err():
  x_to_y(proc.stderr, sys.__stderr__, "<err~ ")

def x_to_y(x, y, prefix=""):
  try:
    while True:
       line = x.readline()
       to_dump = "%s%s" % (prefix, line)
       print >> dump, to_dump
       print to_dump
       y.write(line)
       y.flush()
       dump.flush()
  except:
    pass

recode = None
while recode is None:
  proc_to_me()
  #proc_to_me_err()
  me_to_proc()

  retcode = proc.poll()

exit(retcode)

只需用此脚本替换您的原始二进制文件,然后更改<real app>以创建实际过程。输入和输出信息将被写入屏幕并转储到/tmp/dump.

(但我不确定终止标准,我没有详细检查)

于 2012-06-05T15:31:01.967 回答