A named pipe could work for you. With only a little bit more work you can get one robustly and without having to setup trap
s or similar to handle file-system cleanup afterward - you just do the cleanup beforehand.
pipe=/tmp/$$pipe log=mylog.txt
mkfifo "$pipe"; exec 3<>"$pipe"
{ rm "$pipe"; tee "$log"; } <&3 >/dev/tty &
pipe=$!; exec >&3 3>&-
There. From this moment on all of the script's output is being written to a (used-to-be) named pipe that is being read by a back-grounded tee
process. The named pipe's special file has already been removed from the file-system and so it need not be cleaned-up later and the only references to it that remain are the file-descriptors assigned to your script's stdout
and tee
's stdin
.
That said, it could be wise to setup at least one trap
:
trap "kill PIPE $pipe" 0
...just to ensure that tee
doesn't hang out in the background after your script exits.
If you run into buffering issues - which shouldn't be a problem, I think, since tee
has an open line on /dev/tty
- you might try your luck calling tee
via stdbuf
. stdbuf
's man
page specifically hedges its bets where is tee
concerned though - it notes tee
as an application that is likely to readjust its own buffers after invocation - but is more positive about the interaction than it is for dd
anyway.
echo log: $$ '->' $log
instead of justecho log: $log
. Bothecho
instructions are run in a different shell instance. – Jan 09 '15 at 19:20