6

I'm writing a terminal logging program - think the script command but a bit more featureful. One of the differences is that, whereas script captures stdout, stdin and stderr as one big character stream, I would like to keep them separate and record them as such.

In order to do this, I use the standard approach of running a child shell connected to a pty, but instead of using a single pty with stdin, stdout and stderr all connected to it, I use two ptys - with stdin and stderr connected to one pty, and stdout on the other. This way, the master process can tell what is coming from stdout and what from stderr.

This has, so far, worked fine. However, I'm starting to run into a few issues. For example, when trying to set the number of columns, I get the following:

$stty cols 169

stty: stdout appears redirected, but stdin is the control descriptor

This seems to be a result of this piece of code, which seems to check whether stdout and stderr are both ttys, but complains if they are not the same.

My question, therefore, is this: am I violating any fundamental assumptions about how Posix processes behave by acting in this way? If not, any idea why I'm seeing errors such as this? If so, is there any way I can get around this and still manage to separate stdout and stderr nicely?

Community
  • 1
  • 1
Impredicative
  • 5,039
  • 1
  • 17
  • 43
  • Yeah, I thought this would be a good idea too. I might try it out, but I think I'm going to give up on it - too non-standard as you found out.. Here is what I came up with (single pty) https://github.com/ioquatix/script-runner/blob/master/lib/script-wrapper.py – ioquatix Jul 16 '14 at 12:30
  • I am also trying to do the exact same thing, but not having any luck due to this issue. Perhaps the answer is to spawn the process with both pipes having the same file descriptor, then as soon as it starts to give output, change stderr file descriptor to the other pty? – J.J Dec 08 '15 at 21:58
  • 1
    Any of you fine folks ever figure this out? – hornairs Nov 10 '16 at 14:07

1 Answers1

3

One idea I had about this is to use a process directly on the pty which then runs the target program, e.g.

(wrapper) -> pty -> (controller) -> script

The controller would be responsible for running the script and capturing the stdout and stderr separately, feeding them back to the wrapper, perhaps by some non-std fd, or alternatively, serialising the data before shipping it back, e.g. prefixing output from stderr with stderr: and stdout with stdout: - then in the wrapper deserialize this and feed it back upstream or whatever you want to do with it.

ioquatix
  • 1,411
  • 17
  • 32