Operating System - HP-UX
1822101 Members
3459 Online
109640 Solutions
New Discussion юеВ

Re: exec redirection plus tee? possible?

 
SOLVED
Go to solution
Trever Furnish
Regular Advisor

exec redirection plus tee? possible?

Using the handy functionality of exec to redirect filehandles for an entire script has really cleaned up our scripts:

exec 1>log 2>&1

...but now I'm wondering if there's any way to use that in combination with tee.

The end result that I want is:
- Only specify redirection once, at the beginning of the script.

- Always have stdout go to a log file.

- If the script was run on an interactive terminal, then also have stdout go to the terminal (and still to the logfile).

A simple function to both send a message to a log and to the terminal isn't enough - I need to send stdout both places.

I guess I could buffer all output into variables and then echo it, but that gets ugly.

I think what I really need is some way to attach stdout to two file descriptors and then redirect those file descriptors separately.

Possible? Suggestions?
Hockey PUX?
14 REPLIES 14
Steve Steel
Honored Contributor

Re: exec redirection plus tee? possible?

Hi

Have you ever looked at the script command

It will do what you ask.

You get normal i/o to the screen and a copy in a log.


Steve Steel
If you want truly to understand something, try to change it. (Kurt Lewin)
Trever Furnish
Regular Advisor

Re: exec redirection plus tee? possible?

Script - Hmmm... That's an approach I hadn't thought of. I don't really want to launch a separate sub-shell for every process though and I'm not sure what I'd do with the output on stdout when the script is run non-interactively. That would also complicate quoting quite a bit.
Hockey PUX?
Robin Wakefield
Honored Contributor

Re: exec redirection plus tee? possible?

Hi,

==========================
#!/usr/bin/ksh

exec 1>/tmp/ls.log 2>&1
ls |tee /dev/tty
==========================

this should log to the screen and to the file.

To see if you're in interactive mode, you can use the syntax:

if [ -t 0 ] ; then
...
...
fi


rgds, Robin
John Palmer
Honored Contributor

Re: exec redirection plus tee? possible?

Neither script or tee will do what you want because having used exec, all the output is going to your log file only.

You could experiment with 'tail -f' to display the logfile as it is written to your terminal.

Simple way:

tail -f
You have to ctrl-C the tail command when the script finishes.

Possible scripted way, you may only want to do this if a certain flag is supplied to the script:

CHILD=""
exec 1>log 2>&1
if [[ -t 1 ]]; # controlling terminal exists
then tail -f &
CHILD=${!}
fi
... body of script ...

Yourscript exit code to kill the tail:
if [[ -n ${CHILD} ]];
then kill ${CHILD}
fi
exit

Regards,
John
Trever Furnish
Regular Advisor

Re: exec redirection plus tee? possible?

Robin, thanks, but that method doesn't work - the pipe into tee overrides the redirection from exec for that command.

And if it did work, then I'd be back at the beginning, appending something to every command.
Hockey PUX?
Trever Furnish
Regular Advisor

Re: exec redirection plus tee? possible?

John,

Can't eyeball that one and tell if it'll work, but it's going down the only path I've been able to imagine so far - forking so that one process does the actual work and another displays the output on an interactive terminal. I was really hoping there was a simpler way. :-)
Hockey PUX?
curt larson_1
Honored Contributor

Re: exec redirection plus tee? possible?

well here is one way

#!/usr/bin/ksh

logfile=
tty=$(tty)
exec 3> $tty
if [ -t = 0 ] ;then
/usr/local/bin/outputredirect $tty $logfile |&
exec >&p
else
exec 1>$logfile 2>&1
fi
rest of your script

file outputredirect
#!/usr/bin/ksh
tty=$1
logfile=$2

while read line
do
print $line >> $logfile
print $line > $tty
done

give that a try and see how it works for you.
Jordan Bean
Honored Contributor

Re: exec redirection plus tee? possible?

At the moment I don't have access to either a UNIX or Linux system, so I'll have to wing it. I'm thinking of co-processes... Try this in the POSIX shell:

logfile=$0.log
if [ -t 0 ]
then
tee $logfile |&
exec 1>&p 2>&p
else
exec 1>$logfile 2>&1
fi
Trever Furnish
Regular Advisor

Re: exec redirection plus tee? possible?

Jordan, yours was close but didn't quite work. Curt, yours worked.

BTW, the bits about co-processes in the manual pages never made sense until now - thanks for being great teachers! :-)

Curt, when I first tested your method, I didn't think it worked - not sure how I goofed, but it does work perfectly, so if you want the rest of the points, just post again and I'll assign them.

Thanks for your help, everyone.

Hockey PUX?
Curtis Larson_2
Advisor
Solution

Re: exec redirection plus tee? possible?

a couple of additions,

you probably caught that i left out redirection of stderr to the coprocess.

/usr/local/bin/outputredirect $tty $logfile |&
exec >&p

should have been
/usr/local/bin/outputredirect $tty $logfile |&
exec >&p 2>&p

the file outputredirect works using the tee command also:
#!/usr/bin/ksh
tee -a $2 >$1

but I can not tell you why it works in a seperate file but not as part of the shell script
Curtis Larson_2
Advisor

Re: exec redirection plus tee? possible?

but you don't need the outputredirect file if you use
/usr/bin/ksh -c tee -a $logfile >$tty |&

that way everything can just be in the one shell script.
Jordan Bean
Honored Contributor

Re: exec redirection plus tee? possible?


Oh, I'm being stupid. stdout from the co-process returns to the parent script. This means that, in this case, tee is writing to the log file, but also back to the script.

Jordan Bean
Honored Contributor

Re: exec redirection plus tee? possible?


Got it! Simple fix. You must also tell tee to send stdout to stderr (aka tty) when becoming a co-proc so it doesn't map back to the returning pipe.

logfile=$0.log
if [ -t 0 ]
then
tee $logfile >&2 |&
exec >&p 2>&1
else
exec >$logfile 2>&1
fi

Jordan Bean
Honored Contributor

Re: exec redirection plus tee? possible?


Curtis' method accomplishes the same task.