Newbie: How do I filter output to the screen and writing the orginal output to a file?

M

Mav

Hi, all


I need to write a perl script that execute (using system) command
to do build.

While it is doing the build, I would like to print out the item is
build on the screen,
the orginal build output will go to the a log file (build.log).


@args = ("\"$devPath\\devenv.com\" Solution\\my.sln /build Release");

open (OLDSTDOUT, ">&STDOUT") or die "Couldn't dup STDOUT: $!";
open(STDOUT, "> build.log") || die "Can't redirect stdout";

#once this execute it starts writing to build.log
$buildResult = system(@args);

#The following write to build.log
#--Build Item A
#compiling a1.cpp
#compiling a2.cpp
....
#--Build Item B
#compiling b1.cpp
#compiling b2.cpp
....

At the same time, how do I only print the following on the screen?
#To screen
Build Item A
Build Item B

Do I need to start a another process in order to do it?
How do I filter the STDOUT(to file) at the same time output to screen?


Thanks,
Mav
 
J

John Bokma

Mav said:
Hi, all


I need to write a perl script that execute (using system) command
to do build.

While it is doing the build, I would like to print out the item is
build on the screen,
the orginal build output will go to the a log file (build.log).


@args = ("\"$devPath\\devenv.com\" Solution\\my.sln /build Release");

open (OLDSTDOUT, ">&STDOUT") or die "Couldn't dup STDOUT: $!";
open(STDOUT, "> build.log") || die "Can't redirect stdout";

use or or || this is confusing.
#once this execute it starts writing to build.log
$buildResult = system(@args);

use strict;
use warnings;
#The following write to build.log
#--Build Item A
#compiling a1.cpp
#compiling a2.cpp
...
#--Build Item B
#compiling b1.cpp
#compiling b2.cpp
...

At the same time, how do I only print the following on the screen?
#To screen
Build Item A
Build Item B

Do I need to start a another process in order to do it?
How do I filter the STDOUT(to file) at the same time output to screen?

use a pipe instead of system
 
M

Mav

I need to execute (using system(@args)) in order to get the output.
Would you give me an example? I read the perl section but still don't
quite understand how to make it work for my case.

Any comments or input are welcome.

TIA,
Mav
 
M

Mav

I need to execute (using the system (@args)) in order to get the
output.
Would you give me an example?
I read the perl section for pipe, still don't quite understand how to
make my code work.
Any input or comments are welcome,

TIA,
Mav
 
T

Tad McClellan

Mav said:
I need to execute (using system(@args)) in order to get the output.


system() does not give you the output!

You need something else ("perldoc -f system" may suggest what "else" is).


[ snip 50 lines of upside-down full-quote.
Please do not do that.
]
 
J

Joe Smith

Mav said:
At the same time, how do I only print the following on the screen?
#To screen
Build Item A
Build Item B
How do I filter the STDOUT(to file) at the same time output to screen?

print OLDSTDOUT "Build Item A\n";
system(@args_A);
print OLDSTDOUT "Build Item B\n";
system(@args_B);

-Joe
 
M

Mav

Yes, system(@args) on my case will give me the build output on the
screen.
'coz the args I parse in is execute an application that will print all
the step on the screen.

However, I want to print out only certain pattern on the screen, at
the same time got the orginal output into the log file. (If you look
at my orginal post).

Regards,
Mav


Tad McClellan said:
Mav said:
I need to execute (using system(@args)) in order to get the output.


system() does not give you the output!

You need something else ("perldoc -f system" may suggest what "else" is).


[ snip 50 lines of upside-down full-quote.
Please do not do that.
]
 
J

Jürgen Exner

Mav said:
Yes, system(@args) on my case will give me the build output on the
screen.
'coz the args I parse in is execute an application that will print all
the step on the screen.

And exactly that is the problem. system() doesn't capture the output. This
means
- your application still prints to the terminal
- your Perl program never recieves the output, doesn't know about it, can't
process it, can't filter it, can't do anything with it.
However, I want to print out only certain pattern on the screen, at
the same time got the orginal output into the log file. (If you look
at my orginal post).

Then --as other have suggested already-- use a different method to call the
external application. A method that allows your Perl program to capture and
process the output as needed.

jue
 
D

Daedalus

And exactly that is the problem. system() doesn't capture the output. This

OReilly's Learning Perl (3rd Ed)
"The system function:
....The child process inherits Perl's standard input, standard output, and
standard error..."

There must be something I'm missing.
 
J

Jürgen Exner

Daedalus said:
OReilly's Learning Perl (3rd Ed)
"The system function:
...The child process inherits Perl's standard input, standard output,
and standard error..."

There must be something I'm missing.

Maybe you are missing the meaning of "inherits".
If e.g. the file descriptor STDOUT in the Perl program is linked to a file
"foobar", then the child process will inherit this connection, i.e. in the
child process STDOUT will be linked to "foobar", too.

jue
 
D

Daedalus

And exactly that is the problem. system() doesn't capture the
Maybe you are missing the meaning of "inherits".
If e.g. the file descriptor STDOUT in the Perl program is linked to a file
"foobar", then the child process will inherit this connection, i.e. in the
child process STDOUT will be linked to "foobar", too.

Ok I think I got it. Is this would be a good way to capture the child
process output into perl ?

open PROCRETURN, "@ARGV|"

or maybe

@procreturn = `@ARGV`


Thanks
DAE
 
M

Mav

First of all, I thank for so many people reply my post. However, I
still didn't get my progam working. I think it is because I didn't
explain it correctly.
I will try on this mail:

On my perl script, I would like to execute the command:
@args = ("\"$devPath\\devenv.com\" Solution\\my.sln /build Release");
This is an Vs.net command that allow user to build the solution(my
solution) from the console. Once this command got execute, the output
will print on the SCREEN like:
--Build Item A
compiling a1.cpp
compiling a2.cpp
compiling a3.cpp

...
--Build Item B
compiling b1.cpp
compiling b2.cpp
compiling b3.cpp
...
--Build Item C
compiling c1.cpp
...
However, I don't want all the detail got print on the screen, I want
only key main being print on the SCREEN like,:

--Build Item A
--Build Item B
--Build Item C

But still keep the orignal format in the a log FILE (build.log) which
will contians the
--Build Item A
compiling a1.cpp
compiling a2.cpp
compiling a3.cpp

...
--Build Item B
compiling b1.cpp
compiling b2.cpp
compiling b3.cpp
...
--Build Item C
compiling c1.cpp
...

Is that possible to do?

Thanks,
Mav
 
G

Gunnar Hjalmarsson

Mav said:
I still didn't get my progam working. I think it is because I
didn't explain it correctly.

Or you did not listen to the advices you got. ;-)
On my perl script, I would like to execute the command:
@args =
("\"$devPath\\devenv.com\" Solution\\my.sln /build Release");
This is an Vs.net command that allow user to build the solution(my
solution) from the console. Once this command got execute, the
output will print on the SCREEN like:
--Build Item A
compiling a1.cpp
compiling a2.cpp
compiling a3.cpp

However, I don't want all the detail got print on the screen, I
want only key main being print on the SCREEN like,:

--Build Item A
--Build Item B
--Build Item C

But still keep the orignal format in the a log FILE (build.log)

You may want to try something like this:

my $output = qx(@args);
open LOG, '>> build.log' or die $!;
print LOG $output;
close LOG;
print "$1\n" while $output =~ /^(\s*--.+)/gm;
 
M

Mav

Thanks, only after the build completed
it print out the info. I would like to show up what is building...=(
It will print "Start" and nothing show up...
Do I need to create a seperate process?

#Here is the completed code.
#!/usr/bin/perl

$build_config = Release;

# Setup the path to devenv
my $devPath = $ENV{VS71COMNTOOLS};
$devPath =~ s/\\\w+\\$//;
$devPath =~ s/$/\\IDE\\/;

# Do the build
if (-e "b.log") {
@args = ("del b.log");
system(@args);
}

@args = ("\"$devPath\\devenv.com\" ..\\Solution\\my.sln /build $build_config");

print "Start\n";
my $output = qx(@args);

open LOG, '>> b.log' or die $!;
print LOG $output;
close LOG;
print "$1\n" while $output =~ /^(\s*--.+)/gm;
 
G

Gunnar Hjalmarsson

Mav said:
Thanks, only after the build completed it print out the info. I
would like to show up what is building...=(

Well, I realize that, but it's beyond the scope of my answer. :) Just
wanted to say (like several others have done) that you should not
necessarily use the system() function.

I don't know the complete answer to your question.
 
A

Anno Siegel

Gunnar Hjalmarsson said:
Well, I realize that, but it's beyond the scope of my answer. :) Just
wanted to say (like several others have done) that you should not
necessarily use the system() function.

I don't know the complete answer to your question.

Backticks and qx wait until the background process is finished and
deliver all the output at once. To see the lines of output as they
appear, open a filehandle to capture the output. Untested:

open my $proc, "@args |";
/^(\s*--.+)/ and print "$1\n" while <$proc>;

Anno
 
G

Gunnar Hjalmarsson

Anno said:
Backticks and qx wait until the background process is finished and
deliver all the output at once. To see the lines of output as they
appear, open a filehandle to capture the output. Untested:

open my $proc, "@args |";
/^(\s*--.+)/ and print "$1\n" while <$proc>;

Thanks, Anno!

So, then a solution to the OP's question may be:

open my $log, '>> build.log' or die $!;
open my $proc, "@args |" or die $!;
while (<$proc>) {
print $log $_;
print if /^(\s*--.+)/;
}
close $proc;
close $log;
 
M

Mav

Thanks Gunnar. That is exactly the answer I am looking for.
If I use system(@args) I can get a $buildResult from it.
$buildResult = system(@args); (That will give me return 0 if build successful).

Now, if I am using open:
open my $proc, "@args |" or die $!;
Is that anyway I can get the $buildResult?

Thanks,
Mav
 
G

Gunnar Hjalmarsson

Mav said:
Thanks Gunnar. That is exactly the answer I am looking for.

Good, but don't forget to thank Anno who provided the actual solution...
If I use system(@args) I can get a $buildResult from it.
$buildResult = system(@args); (That will give me return 0 if build
successful).

Now, if I am using open:
open my $proc, "@args |" or die $!;
Is that anyway I can get the $buildResult?

You can check the return value from close():

close $proc or die "Build failed $! $?";
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top