Redirecting command output as well as commands

I have a Bourne Shell script that is normally run as a background job and redirects it's output to a file internally (using exec >>); I use "set -x" to capture each command which provides me with a nice shell execution log if it all goes to pieces.

I now also need to be able to also run this as an interactive script whilst still keeping the "execution log" concept but have the output from certain commands also printed on the user terminal so they know what's going on during the long sections whilst keeping them in the log as well.

The following Sample Script shows on screen the output from msg() and the output from awk;
'user.log' is fine as a printable logfile;
'exec.log' shows everything BUT the output from awk

QUESTION (finally) - how can I get the output from awk to show on the original script stdout (ie user screen) AND also into exec.log

Sample Script:

msg() {
    echo `date "+%a %b %d %T"` "$*"  | tee -a user.log 1>&3
}
LOG=exec.log
exec 3>&1                    # remember original stdout (ie user screen)
exec >> $LOG 2>&1        # send stdout/stderr to execution log $LOG
msg "Commenced"          # shows on screen & into 'user.log'
set -x                         # show commands as they run
# use awk to print delayed messages to screen - also want o/p in $LOG
awk 'BEGIN {for(i=0;i<5;i++){printf "\rHelloooo" i;system("sleep 1")};print "";exit }' 1>&3
msg Ended                  # appears on screen, in user.log & $LOG
exit

Any advice/script fragments would be appreciated

awk ... [echo this part to stdout] | tee -a log.txt

:wink:

I've tried using tee already -

adding 'tee -u -a exec.log' simply sends the output only to exec.log
adding 'tee -u -a exec.log 1>&3' doesn't add anything to exec.log

I need to get the output from 'awk' on the screen AND into exec.log
as well as getting the shell to send it's stderr to exec.log :confused:

Perhaps I should add that I'm testing on SCO Unix:( (with a plan on using on SUSE Linux once it works) so I'm really restricted as to what I can do

---------- Post updated at 08:56 AM ---------- Previous update was at 05:45 AM ----------

I've been thinking and found the answer ... not elegant but it works :smiley:

create a macro that read characters and echoes them where I need them ensuring that we can't see the commands execute with the macro (could be a separate shell script I suppose to do same)

listen() {
    exec 6>&2  
    exec 2>&-
    ok=1
    while [ $ok -eq 1 ]; do
        x=`dd bs=1 count=1`
        case "$x" in
        "") ok=0; continue ;;
        esac
        echo -n $x
        echo -n $x >&3
    done
    echo "" >&3
    exec 2>&6
}

and change the 'awk' command to be

awk 'BEGIN {for(i=0;i<5;i++) {printf "\rHelloooo" i;system("sleep 1") };print "";exit }' | listen

and presto ... I get the output to original stdout AND into my 'exec.log' as I wanted

if you can improve on this please feel free to post:)

mmh wouldn't it work if you just redirect the awk output with > into a variable and then echo and print/write it out?
like:

awk ... > supercoolvariable
echo $supercoolvariable
echo $supercoolvariable > exec.log

I'm using awk here as an example; the program I actually need to use is wodim writing to data a DVD and it takes about 15 minutes; all the time it is interactively outputting status messages that I need the user to see so they won't think it's all gone horribly wrong