3

What I want though is to run a program and log both the stdin and stdout, but I want the stdin to be supplied from a file.

I thought script log.txt < input.txt would work, but it does not, because the stdin does not get logged, only the output gets logged.

Where input.txt is

./program
something for the stdin of program
some more stuff
Buge
  • 131
  • 1
  • 5
  • There's a similar question here – don_crissti Apr 17 '15 at 10:35
  • 1
    There is a problem with interleaving log of stdin and stdout: Input and output can happen concurrently, or even physically in parallel on a multiprocessor machine. That means that there is no defined order for the characters in both streams combined. So the log is merged in a somewhat random way (except there is coordination). In many cases, output is buffered by line, which makes the interleaving line by line - mostly working fine. But it happens that there are random effects, which are hard to understand when buffering is involved. – Volker Siegel Apr 21 '15 at 21:44

3 Answers3

2

This is probably not the prettiest solution, but you can do something like:

cat file.txt | tee -a stdin.txt | ./program | tee -a stdout.txt

You could use the same file in both tees, but your input and output might get mangled and unreadable.

Fox
  • 466
0

You already have the stdin log: that's your file.

Otherwise (not sure if this is what you're trying to accomplish), if you rather want a log containing both the stdin and stdout interspersed, you could modify your program to send the lines from stdin to stdout as they're read, before they are processed.

dr_
  • 29,602
  • I want the log to be interleaved into a single file, like the script command does. What if I cannot modify the program? – Buge Apr 17 '15 at 07:59
0

I ended up hacking this thing together:

import subprocess
import time
import sys

log = open(sys.argv[3], 'w')

input = open(sys.argv[2], 'r')

p = subprocess.Popen([sys.argv[1]], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

def readAllSoFar(proc, retVal=''):
  while (subprocess.select.select([proc.stdout],[],[],0)[0]!=[]):
    retVal+=proc.stdout.read(1)
  return retVal

while True:
    print('starting loop')
    line = input.readline()
    print('read line ' + line)
    if not line:
        print('breaking')
        break

    print('before sleep1')
    time.sleep(0.1)
    print('before readAllSoFar')
    output = readAllSoFar(p)
    print('got output' + output)
    log.write(output)
    time.sleep(0.1)
    log.write(line)
    p.stdin.write(line)

Run it with python runner.py ./program_to_run input.txt output.txt

It assumes any output from a command will be done in a tenth of a second.

Buge
  • 131
  • 1
  • 5