0

I am writing a Perl script to automate some software installation.

In my script I run another bash script and take its output and print it again.

print `/home/me/build.sh`;

but build.sh script take 8 minutes, so my script wait till the 8 minutes and script finishes the starting in printing the output.

How can I print each line from the build.sh program as it is running in bash shell?

As the comment below I use system ("/home/me/build.sh");

but the output goes to shell however I make out redirection in my script to my log file,

open $fh, "> filename";
*STDOUT = $fh;
*STDERR = $fh;

Then should when I use system function its output will be redirected to filename, but it isn't.

Should I use print system ("/home/me/build.sh"); instead of system ("/home/me/build.sh");?

#

The full code:

#!/usr/bin/perl

use strict;
use warnings;

use IO::File;

my %DELIVERIES = ();
my $APP_PATH = $ENV{HOME};
my $LOG_DIR = "$APP_PATH/logs";
my ($PRG_NAME) = $0 =~ /^[\/.].*\/([a-zA-Z]*.*)/;

main(@argv);

sub main
{
        my @comps = components_name();
        my $comp;
        my $pid;

        while ( scalar @comps ) {
                $comp = pop @comps;
                if ( ! ($pid = fork) ) {
                        my $filename = lc "$LOG_DIR/$comp.log";

                        print "$comp delpoyment started, see $filename\n";

                        open (my $logFile, ">", "$filename") or (die "$PRG_NAME: $!" && exit);
                        *STDOUT = $logFile;
                        *STDERR = $logFile;

                        deploy_component ( $comp );

                        exit 0;
                }
        }
        my $res = waitpid (-1, 0);
}


sub components_name
{
        my $FILENAME="$ENV{HOME}/components";
        my @comps = ();

        my $fh = IO::File->new($FILENAME, "r");

        while (<$fh>)
        {
                push (@comps, $1) if /._(.*?)_.*/;
                chomp ($DELIVERIES{$1} = $_);
        }

        return @comps;
}

sub deploy_component
{
        my $comp_name = shift;

        print "\t[umask]: Changing umask to 007\n";
        `umask 007`;

        print "\t[Deploing]: Start the build.sh command\n\n";
        open (PIPE, "-|", "/build.sh");
        print while(<PIPE>);
}
7
  • try adding $|++ at the top of your script Commented Oct 8, 2013 at 7:26
  • 1
    it's not duplicated because, here I made output redirection at start of my script. Commented Oct 8, 2013 at 8:38
  • @M_E clever you! didn't mention earlier that you want it to redirect to file. initial print ` ` didn't make any sense Commented Oct 8, 2013 at 9:47
  • @jkshah And How said that print `` will make redirection?! read it again carefully, PLEASE. Commented Oct 8, 2013 at 9:56
  • @M_E then isn't system ("/home/me/build.sh | tee filename"); sufficient? Commented Oct 8, 2013 at 10:03

2 Answers 2

6

A more flexible way is to use pipe.

open PIPE, "/home/me/build.sh |";
open FILE, ">filename";
while (<PIPE>) {
    print $_;           # print to standard output
    print FILE $_;      # print to filename
}
close PIPE;
close FILE;

BTW, print system ("/home/me/build.sh"); will print the return value of system(), which is the exit status of your shell script, not the output wanted.

Sign up to request clarification or add additional context in comments.

8 Comments

I have a question, Is build.sh will finish first the the while starts?
@M_E No. They're two processes running simultaneously. The child process (the shell script) generates outputs and write them to the pipe, and the parent process (the perl script) fetch from the pipe when there's a new line.
open (PIPE, "-|", "/home/me/build.sh"); print while(<PIPE>); Here print will use STDOUT and I made output redirection, but still it prints on the shell, why this?
@M_E Show me your code of redirection. In the code above I didn't see anything related to the redirection.
open $fh, "> filename"; *STDOUT = $fh; *STDERR = $fh; Isn't it redirection?
|
0

How can I print each line from the build.sh program as it is running in bash shell?

Possible Solution: You can try the following

system ("sh /home/me/build.sh | tee fileName");

The above statement will show the output of build.sh on the console and at the same time write that output in the filename provided as the argument for tee

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.