rahuL
rahuL

Reputation: 3420

Printing a progress bar during execution of a command in Perl-CGI

I want to display an iterative progress bar during the execution of a particular command in my Perl-CGI program. I use the CGI::ProgressBar module to achieve this. For example, if I want to show the progress bar during the execution of an RKHunter scan, this is the code I wrote:

use CGI::ProgressBar qw/:standard/; $| = 1;

    print progress_bar( -from=>1, -to=>100 );
    open(my $quik_rk, '-|', 'rkhunter', '--enable', '"known_rkts"') or print "ERROR RUNNING BASIC ROOTKIT CHECK!!";
    # print the progress bar while the command executes     
    while(<$quik_rk>)
    {
            print update_progress_bar;
            #print "<img src=\"ajax-loader.gif\"></img>";
    }
    close($quik_rk);

This works fine. However, I try the same on another command(this one's to scan using Linux Maldet) immediate after the code above:

    open(my $quik_lmd, '-|', 'maldet', '-a', '/home?/?/public_html') or print "ERROR RUNNING BASIC MALWARE CHECK!!";
    my $this_ctr = 0;
    while(<$quik_lmd>)
    {       $this_ctr++;
            print update_progress_bar;

    }
    close($quik_lmd);

The progress bar doesn't execute but te command itself runs in the background.

What am I doing wrong? Is there a better way to show a progress bar on a browser in Perl-CGI?

Upvotes: 0

Views: 1645

Answers (1)

codnodder
codnodder

Reputation: 1675

I am not familiar with RKHunter, but based on your results my guess is that it outputs a line of text for each test it runs, while the other command does not.

Each line of text output by RKHunter will trigger the next iteration of <$quik_rk>.

The second command, <$quik_lmd>, it is likely silent, so it never triggers the loop. Once the command terminates, execution continues after your while.

The key bit here is "line of text". The <$filehandle> operator returns a line of text each time it sees a newline character. In order to do what you want using this construct, you would need to coerce the second command into being verbose about it's activities, and most importantly, to be verbose with a lot of newlines.

Alternatively, you can open a background process and use sleep to manage your loop, e.g.,

use strict;
use POSIX qw(WNOHANG);
my $pid = open(my $quik_rk, '-|', 'sleep', '5'); # replace with your command
do {
    print "waiting\n"; # update_progress_bar;
    sleep 1; # seconds between update
} while (waitpid($pid, WNOHANG)==0);

Upvotes: 1

Related Questions