2012-05-29 16 views
1

我想捕獲命令行程序(即GDB,但爲了簡單起見目前已更改爲lscat)的所有輸入和輸出,並將其重定向到一個文件中,以供稍後使用分析。如何截取stdin/out/err透明

我無法接近任何工作,但我不明白是什麼錯。 這是我最後一次嘗試:

#!/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) 

我嘗試了其他幾個選項,比如 - 寫文件包,這是應該寫入/外部文件都寫入標準輸入讀取標準輸出,犯錯 - 命名管道 - ...

但我得到的最好的是「ls」的第一行。

此外,GDB依靠readline進行CLI版本,我覺得它不會那麼容易被透明地捕獲!

回答

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

(但我不確定終止標準,但沒有詳細檢查)

+0

任何類似的C++解決方案(但沒有分叉)? http://stackoverflow.com/questions/26480332/how-to-intercept-llvm-lli-tool-input-output – 4ntoine