On linux you can address an application's file-descriptors as named files in /dev/fd/[0-9]
. And what you definitely can do with a named file and an input stream is tee
the input into that file and to stdout. And so what I usually do when I find myself in your situation (as I often do) is tee
input off to both my reading application and to /dev/fd/2
- stderr.
Like this:
seq 10 | tee /dev/fd/2 | wc -c
1
2
3
4
5
6
7
8
9
10
21
Of course, even if you weren't on a linux system the same thing might be done portably - if less specifically in some cases - by just doing ...| tee /dev/tty | ...
If you're talking about the terminal when you say stdin
(as your link indicates), then you might still do the same thing, though it can get a little more tricky that way because of the kernel's line-buffering. And so what I would do in that case is to log all tty
i/o by wrapping my command in luit
- because I find it the more convenient of the two -though script
could also work in much the same way.
luit
is probably already installed on your system - it is typically packaged w/ xterm
- and it is a very simple cli tool intended to do UTF-8 translations (which function might be disabled entirely via cli switch, but I've never found a reason to do so) for terminal applications which don't understand it.
It works by layering its own pty - for which it owns the master fd - beneath the current tty layer and copying all i/o from the current session to its child layer, where it execs your requested application. Because it owns the master end, it can easily duplicate all i/o it reads/writes elsewhere as it likes, and it provides a convenient means of asking it to do so:
luit -olog /dev/fd/2 sh -c 'read var; echo "$var"'
eecchhoo tthhiiss vvaarr??????
echo this var???
echo this var???
Where, as you can see, luit
logs to its named -olog
file all terminal input received as soon as it does.
Using /dev/fd/2
isn't nearly as useful in that case - as all of the i/o winds up at the same place twice. I usually prefer to open a second terminal, query its name with the tty
command, and use that /dev/pts/[0-9]
name as luit
/script
's named outfile - which will copy all of the i/o to both terminals simultaneously - so I can read/review it on one, and interact with it on the other. tee
can be used to do the same thing in most cases, but it doesn't typically have the advantage of the master end of a pty to recommend it.
If your purpose is just as you say - to copy over for your review all of some process's input - then you would probably do best to focus on the input. strace
is useful for many things, but if you're trying to get an accurate report of typical behavior, then it stands to reason that you should probably modify that behavior as little as possible while gathering your report. In other words, if you want input, copy input, don't insert a debugging parent process which will -TRAP
and pause your process every time it makes a syscall.