Writting to a logfile and to the Screen in Linux

While writing a complicated script, I found that I was in need of a way of writing to both Standard Out, and to the Syslog. Try as I might, I couldn’t find a way to do this, or at least, I couldn’t think of a way to do this that didn’t duplicate code, and didn’t require me to mess about with temporary log files for holding data.

During my search, I came across an article about re-directing Standard Error and Standard Out to a file at the same time. I spent a bit of time reading it, and found that it was very difficult to understand, plus it didn’t exactly do what I wanted it to do, however, it did give me the idea on how to do what I wanted.

The secret is in the FIFO(First In, First Out) file. This is a special kind of file that is normally used for IPC (Inter-Process Communication). You can have one program read from the file, and the other wright to the file. Sort of like a network Socket, you have a server that is listening, and a program that is sending data.

Using the script at Travis Hartwell’s site, I’ll try and walk through the steps that I went through, with a bit more explanation of both my modifications, and his script.

The first thing it does is to create the FIFO file, using mkfifo. This gives us our basic “Socket” to play with:


if [ ! -e $OUTPUT_PIPE ]; then
mkfifo $OUTPUT_PIPE
fi

In Travis’ Script, he then goes on to create a another file that he’s going to log too. We don’t want to log to an ordinary file, rather, we’d like to log to the Syslog:


if [ ! -e $OUTPUT_LOG ]; then
mkfifo $OUTPUT_LOG
fi

Here you’ll notice that I’ve created another FIFO. We now need this to have something to output too. Currently it doesn’t do anything interesting, so lets make it be intersteing:


exec cat $OUTPUT_LOG | logger -t "Jara23" &

Lets go through this command by command. exec executes the command in the current process, rather than spawning another process to deal with this. We need this command in this process so that future commands that wright to this work. cat $OUTPUT_LOG is nice and smiple cat the contents of $OUTPUT_LOG to Standard In. | logger -t “Jara23” & Pipe the result of this cat to the logger program, using the tag “Jara23”. Personal Note: This might be worth trying in a bigger script to check for errors

Next comes the Heart of the script. Without this little snippet of code, I would never have worked this out.


exec 3>&1 4>&2
tee $OUTPUT_LOG < $OUTPUT_PIPE >&3 &
tpid=$!
exec > $OUTPUT_PIPE 2>&1

Looks Scary and Complicated doesn’t it? I found it very scary. The first line redirects two special pipes, 3 and and 4 to Standard In and Standard Error respectively.

The next line uses tee, a useful little program that will wright to a file and to Standard Out. As you can see, here it will wright to our special pipe that we’ve set up to wright to the logger, and to the OutputPipe, and we put the command to run in the background under this shell. We capture the PID (the process Identifier). We now redirect all of the output of the script to run through our named pipe.

Remember, of course, to close the file descriptors (as shown in the example script), otherwise your script will hang, as though waiting for more input or output, which it is.

I hope this helps,

Black Xanthus


Posted

in

,

by

Tags:

Comments

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.