1

I'm trying to store both STDOUT and STDERR from the terminal (and if possible STDIN given by user) in a file for every command.

So i started creating a trap function to execute every command in a edited manner like:

shopt -s extdebug

preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND

    eval `history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"` |& tee ~/recent_output.txt
    return 1 # This prevent executing of original command
}
trap 'preexec_invoke_exec' DEBUG


and saving the above file and executing

source file.sh

This did the work what i wanted but stopped some commands from executing like

cd ..

The reason for this was piping creates a sub-shell and then executes every command in it. So the main shell remains unaffected.

Even the script functionality of bash i.e

script ~/recent_output.txt

worked but only gives output after you do exit in in terminal

So, basically i want to store/get the output of previous command executed in the bash terminal. You can help me with any language (golang,python...).

iomonad
  • 42
  • 1
  • 7
Biswajit
  • 25
  • 7
  • "eval \`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"\`" why eval? – KamilCuk Oct 15 '19 at 10:48
  • it is because `history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"` outputs a string and eval can execute that – Biswajit Oct 15 '19 at 12:56
  • Why not just use [`script`](http://man7.org/linux/man-pages/man1/script.1.html)? I fear that `eval` will be horrible at handling corner cases, quotes, multiline commands, etc. Ex doing herodoc from terminal will fail miserably with your `eval`. Why not just `eval "$BASH_COMMAND"`? What if user does `set +o history`. – KamilCuk Oct 15 '19 at 12:57
  • But the problem with these commands is that, they create a new subshell and executes them but i want to execute in the same shell – Biswajit Oct 15 '19 at 13:00
  • 2
    `in the same shell` so maybe redirect stdout and stderr? like `exec 1> >(tee stdout.txt)` `exec 2> >(tee stderr.txt)`. Like `exec 3>&2 2> >(tee stderr >&3)` – KamilCuk Oct 15 '19 at 13:03
  • Why note use 'set -x' + capture the input/output/error to files ? – dash-o Oct 15 '19 at 13:03
  • I had this in my copy buffer from an earlier question: https://asciinema.org/ – Gem Taylor Oct 15 '19 at 18:10
  • @dash-o can u provide the exact command – Biswajit Oct 15 '19 at 18:52

1 Answers1

1

It is possible to capture commands, stderr and stdout of a bash script (say x.sh), using:

bash -x x.sh 2> >(tee err.txt) | tee out.txt

The err.txt will capture the executed commands (prefixed with '+'), and the stderr of each command. The out.txt will capture the output

dash-o
  • 13,723
  • 1
  • 10
  • 37