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>);
}
Mahmoud Emam
  • 1,499
  • 4
  • 20
  • 37

2 Answers2

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.

Logan Ding
  • 1,761
  • 1
  • 12
  • 23
  • 1
    I have a question, Is `build.sh` will finish first the the `while` starts? – Mahmoud Emam Oct 08 '13 at 08:43
  • 2
    @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. – Logan Ding Oct 08 '13 at 08:46
  • `open (PIPE, "-|", "/home/me/build.sh"); print while();` Here print will use `STDOUT` and I made output redirection, but still it prints on the shell, why this? – Mahmoud Emam Oct 08 '13 at 09:26
  • @M_E Show me your code of redirection. In the code above I didn't see anything related to the redirection. – Logan Ding Oct 08 '13 at 09:32
  • `open $fh, "> filename"; *STDOUT = $fh; *STDERR = $fh;` Isn't it redirection? – Mahmoud Emam Oct 08 '13 at 09:36
  • @M_E Could you update your question and put your current code together? I think this should work but there might be other problems? – Logan Ding Oct 08 '13 at 09:53
  • I added the full code. – Mahmoud Emam Oct 08 '13 at 10:06
  • I checked your code and write a simplified test version, but didn't find any problem, the output was printed to the log file. It's really odd, maybe you should use `perl -d` to debug it. – Logan Ding Oct 08 '13 at 12:51
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

Jayesh Elamgodil
  • 1,467
  • 11
  • 15