Reputation: 61
What I want to obtain is logging all the output of a script to a file, all in the script itself, saving all I see on the screen in the log file. If I don't redirect to file the script works as intended, continuing to loop forever till I hit CTRL+C; when this happens it prints a couple of messages on screen and quits. If I try to redirect to a file, using tee, not only it doesn't print the messages but also the log is incomplete, there's only the loop lines, nothing afte that. Here's the script (cut down version):
#!/bin/sh
EXIT=0
COUNT=0
{
while [ $EXIT -eq 0 ]
do
COUNT=$((COUNT+1)) && echo "Eternal loop $COUNT" && sleep 1
trap 'EXIT=1; echo "Loop interrupted by user, exiting."' 15 2 8 20
done
echo "Out of loop, eternity ends"
} | tee log.log 2>&1
I read around and couldn't understand if the issue I have is caused by piping to tee, by stderr and stdout, or by how I useda trap. I'm a noob at shell scripting and this is frustrating, any help will be appreciated. Thanks.
Edit 1: After reading chepner's answer I modified the script like this:
#!/bin/sh
EXIT=0
COUNT=0
rm log.log
while [ $EXIT -eq 0 ]
do
COUNT=$((COUNT+1)) && echo "Eternal loop $COUNT" | tee -a log.log && sleep 1
trap 'EXIT=1; echo "Loop interrupted by user, exiting." | tee -a log.log' 15 2 8 20
done
echo "Out of loop, eternity ends" | tee -a log.log
and it works, it logs the output to a logfile, and I still see the output on screen, exactly how I wanted. Will have to try it on the other script, but I suppose it'll be OK. Now a question remains: if I have lots of commands instead of just 3, would this solution be "clean" enough? I mean, what happens to all those tee I call forth? Is there a better way to do this, like more polished?
Upvotes: 4
Views: 7538
Reputation: 532303
With the pipeline, the foreground job consists of two processes, one for each side of the pipeline. Hitting Control-C sends SIGINT
to all processes, so that there is no chance for the post-loop echo
to run, or for tee
to output the final output of the LHS process. Without the pipe to tee
, the while
loop is running entirely inside the current shell instance, so the the shell itself receives the SIGINT
and (I believe) only interrupts whatever shell command is currently running in the loop. The trap fires, and then the loop exits naturally as a result of the condition check on EXIT
.
Upvotes: 3
Reputation: 1169
Not exactly what you're asking, but when you want to log everything you see during a process, the script command is easier than dealing with redirection.
if you want to use tee anyway, move the redirection in front of the pipe
somecommand 2>&1 | tee outfile
Upvotes: 6
Reputation: 7028
Maybe you want to redirect stderr
to stdout
and then pipe to tee
command:
...
} 2>&1 | tee log.log
Upvotes: 1