5

So I want to record my bash interaction, which I know I can do with script, or ttyrec. Except I want one feature more than they have. Save input (i.e STDIN), and output (i.e. STDOUT) separately.

So something like (where I typed the first "Hello World!"), except of course script takes one [file] arg, not two:

user@pc:~$ script input.txt output.txt
Script started
user@pc:~$ paste > textfile.txt
Hello World!
user@pc:~$ cat textfile.txt 
Hello World!
user@pc:~$ exit
Script done

So input.txt looks like:

user@pc:~$ paste > textfile.txt
Hello World!
user@pc:~$ cat textfile.txt 
user@pc:~$ exit

And output.txt looks like:

Hello World!
exit

So I want a program like script which saves STDIN & STDOUT separately. Since currently, this would be the normal output of script (which I do not want, and need seperated):

Script started

user@pc:~$ paste > textfile.txt
Hello World!
user@pc:~$ cat textfile.txt 
Hello World!
user@pc:~$ exit
exit

Script done

Does this exist, or is this possible?

Note the usage of paste command, since I had considered filtering the ouput file based on user@pc:~$, but in my case (as with paste) this would not work.

ptolemy0
  • 799
  • 1
  • 5
  • 13
  • 1
    If you want the prompts in `input.txt` as well, be aware that the shell prints the prompt to standard error, and it may be difficult to separate the prompt from text that other programs write to standard error. – chepner Feb 19 '19 at 17:37
  • You would have to put something between stdin and the shell. Something like `cat | tee input.txt | sh -i | tee output.txt`. – KamilCuk Feb 19 '19 at 21:41
  • 1
    Saving stdin and stdout separately is trivial (*slightly* tricky if you want to retain TTY-ness, in which case you'd want to instrument `screen` or `tmux` or the like, but generally: put one `tee` on each side and you're done). Saving stdout and stderr separately without losing ordering is damned hard (and requires the class of tool discussed in jhnc's answer or my comment thereto). – Charles Duffy Feb 20 '19 at 03:19

1 Answers1

5

empty

empty is packaged for various linux distributions (it is empty-expect on ubuntu).

  1. open two terminals
  2. terminal 1 : run empty -f -i in.fifo -o out.fifo bash
  3. terminal 1 : run tee stdout.log <out.fifo
  4. terminal 2 : run stty -icanon -isig eol \001; tee stdin.log >in.fifo
  5. type commands into terminal 2, watch the output in terminal 1
    • fix terminal settings with stty icanon isig -echo
    • log stderr separately from stdout with exec 2>stderr.log
    • when finished, exit the bash shell; both tee commands will quit
  6. stdout.log and stdin.log contain the logs

Some other options:

peekfd

You could try peekfd (part of the psmisc package). It probably needs to be run as root:

peekfd -c pid fd fd ... > logfile

where pid is the process to attach to, -c says to attach to children too, and fd are list of file descriptors to watch (basically 0, 1, 2). There are various other options to tweak the output.

The logfile will need postprocessing to match your requirements.

SystemTap and similar

Over on unix stackexchange, use of the SystemTap tool has been proposed. However, it is not trivial to configure and you'll still have to write a module that separates stdin and stdout.

sysdig and bpftrace also look interesting.

LD_PRELOAD / strace / ltrace

Using LD_PRELOAD, you can wrap lowlevel calls such as write(2).

You can run your shell under strace or ltrace and record data passed to system and library functions (such as write). Lots of postprocessing needed:

ltrace -f -o ltrace.log -s 10000000000 -e write bash

patch ttyrec

ttyrec.c is only 500 lines of fairly straightforward code and looks like it would be fairly easy to patch to use multiple logfiles.

jhnc
  • 11,310
  • 1
  • 9
  • 26
  • 1
    FYI, I've implemented a closely related tool (tracking stdout/stderr distinctly with ordering retained) on top of sysdig here on this site; see [Separately redirecting and recombining stderr/stdout without losing ordering](https://stackoverflow.com/questions/45760692/separately-redirecting-and-recombining-stderr-stdout-without-losing-ordering). Didn't include timing data there, but just retaining the original sysdig trace would have the effect. – Charles Duffy Feb 20 '19 at 03:22
  • @CharlesDuffy Nice. I gave up on systemtap as ubuntu's packages don't play well with secure boot. Hadn't come across sysdig but it is offering to enroll a new MOK so I'm going to reboot and have a play... – jhnc Feb 20 '19 at 03:28
  • Awesome answer! So I went with the last option, making a patch (for script), although in a basic way. So it outputs special characters for the different streams, then RegEx the output into different files afterwards. Messy - but it worked! Thanks! – ptolemy0 Feb 20 '19 at 15:33