bash redirection question
Steven W. Orr
steveo at syslang.net
Fri Nov 7 16:51:07 EST 2003
On Friday, Nov 7th 2003 at 16:18 -0500, quoth Kevin D. Clark:
=>
=>Kenny Donahue writes:
=>
=>> I have a c program that gathers a bunch of information then writes
=>> this information to a file. The c program then calls a bash script with
=>> the file that was created as an argument. The bash script sources the
=>> file and does things according to what was set in the file.
=>>
=>> Now the problem. I'd like to use the same log file for the c program
=>> and the shell script. Since I'm making calls in the script such as insmod,
=>> rm, lsmod, rmod. etc... I'd like to redirect the output from
=>> 1. My echos
=>> 2. stdio from all system calls
=>> 3. stderr from all system calls
=>> But still have everything displayed on the screen
=>>
=>> I'd like to do this without appending " | tee -a $log_file"
=>> to everything.
=>
=>Honestly, if I were doing this on a system upon which I knew that
=>/bin/sh was in fact bash, I'd just modify your C program to invoke the
=>shell script with system(), and I'd just invoke it thusly:
=>
=> system("your-script 2>&1 | tee log_file");
=>
=>(error detection elided...)
=>
=>You seem to be worried about appending "tee -a $log_file" to every
=>command in your script -- I agree, this would be slightly gross. The
=>solution that I have proposed avoids this.
That's the great thing about shell questions. So many ways to say the same
thing. And only *my* way is right. ;-) The trick here is that you want
both the C code and the resulting shell script to have both stdout and
stderr dup'd onto both the screen and to your logfile. If you use the
above proposed call to system then only the shell script would be logging
to the logfile. What's needed is for stdout and stderr in the C program to
go to both the screen and to stderr. Then when the C program starts the
shell script, the script will inherit the already set descriptors.
First of all, if you use the 2>&1 | tee logfile trick, you should be aware
that things just might not display correctly because buffering will be
disturbed by the pipe.
Another trick to use is to script it. See the script(1) command. It will
capture *everything* in a file.
So, if you still want to pipe to tee...
First you check an environment variable when you start your C
program. If it's not set then set it and re-exec yourself but this time
using the pipe to tee trick. (You could also use a program option like -s
to get the same message across.
if ( ! getenv ( "HaveIBeenHereBefore" ) )
{
setenv ( "HaveIBeenHereBefore", "1", 1 );
/* This assumes that you are called with one arg. */
sprintf ( cmd, "%s %s 2>&1 | tee %s", argv[0], argv[1], logfile );
system ( cmd );
}
/* Keep on going. */
blah blah blah;
Another way to go is for your C program to fork and exec a child process
to be the tee. Then the shell script would also inherit the stdout/stderr
descriptors which are also shared (inherited) by the tee process.
Make sense?
--
-Time flies like the wind. Fruit flies like a banana. Stranger things have -
-happened but none stranger than this. Does your driver's license say Organ
-Donor?Black holes are where God divided by zero. Listen to me! We are all-
-individuals! What if this weren't a hypothetical question?
steveo at syslang.net
More information about the gnhlug-discuss
mailing list