2

In reference to https://stackoverflow.com/a/11886837/1996022 (also shamelessly stole the title) where the question is how to capture the script's output I would like to know how I can additionally capture the scripts input. Mainly so scripts that also have user input produce complete logs.

I tried things like

exec 3< <(tee -ia foo.log <&3)
exec <&3 <(tee -ia foo.log <&3)

But nothing seems to work. I'm probably just missing something.

BrainStone
  • 3,028
  • 6
  • 32
  • 59

2 Answers2

3

Maybe it'd be easier to use the script command? You could either have your users run the script with script directly, or do something kind of funky like this:

#!/bin/bash

main() {
    read -r -p "Input string: "
    echo "User input: $REPLY"
}

if [ "$1" = "--log" ]; then
    # If the first argument is "--log", shift the arg
    # out and run main
    shift
    main "$@"
else
    # If run without log, re-run this script within a
    # script command so all script I/O is logged
    script -q -c "$0 --log $*" test.log
fi

Unfortunately, you can't pass a function to script -c which is why the double-call is necessary in this method.

If it's acceptable to have two scripts, you could also have a user-facing script that just calls the non-user-facing script with script:

script_for_users.sh
--------------------
#!/bin/sh
script -q -c "/path/to/real_script.sh" <log path>
real_script.sh
---------------
#!/bin/sh
<Normal business logic>
John Moon
  • 924
  • 6
  • 10
  • This is a surprisingly good solution! I'm shocked I haven't seen this before. – BrainStone Jun 09 '20 at 21:35
  • Btw it should be ``script -q -c "$0 --log${@@Q}" test.log`` for proper escaping. – BrainStone Jun 09 '20 at 21:42
  • The `${@@Q}` syntax errors out for me with bash v4.2... In general since we're expanding the parameters within a double-quoted string, it makes sense to use `$*` to avoid splitting the fields. See https://github.com/koalaman/shellcheck/wiki/SC2145. – John Moon Jun 09 '20 at 21:55
  • Yes it requires a relatively recent version of bash. It's working for me with bash 5.0.3. And it should have been `script -qec "$0 --log ${*@Q}" test.log; exit $?`. And lastly ``$*`` breaks if you have arguments that contain spaces. `"${*@Q}"` properly escapes them. – BrainStone Jun 09 '20 at 22:05
0

It's simpler:

#! /bin/bash
tee ~/log | your_script

The wonderful thing is your_script can be a function, command or a {} command block!

Nikita Malyavin
  • 1,868
  • 1
  • 12
  • 10