Perl 多进程进度条

具体的请根据个人需要修改代码。

#!/usr/local/bin/perl5

    use warnings;
    use strict;
    use Fcntl;
    use Term::Cap;
    use Parallel::ForkManager;

    #==============================
    # for terminal control
    #==============================
    my $termios = new POSIX::Termios;
    my $terminal = Term::Cap->Tgetent ({ TERM => undef, OSPEED => $termios->getospeed });
    $terminal->Trequire(qw(cm sc rc)); #check if terminal support these capabilities
    my $c = `clear`;
    print $c;

    #==============================
    # for fifo
    #==============================
    my $fpath = "myfifo";
    unless (-p $fpath) {
        if (-e _) {
            die "$fpath is something unknow\n";
        }
        else {
            require POSIX;
            POSIX::mkfifo($fpath, 0666) or die "can not mknod $fpath: $!";
            print "$0: created $fpath as a named pipe\n";
        }
    }
    else {
        print "$0: named pipe $fpath exists\n";
    }


    #==============================
    # for parallel processes
    #==============================
    my @names;
    push @names, "p$_" foreach 0..5;
    my $childs;
    $childs->{$_} = {total=>1, processed=>0, name => $names[$_]} foreach(0.. $#names);
    my $remain_child_process = scalar @names;

    $SIG{PIPE} = sub {
        -- $remain_child_process;
        print STDERR "pipe broken\n";
    };


    #==============================
    # main program
    #==============================
    my $now = time;
    my $pm =  new Parallel::ForkManager(scalar @names);
    foreach my $child ( 0 .. $#names ) {
        my $pid = $pm->start($names[$child]) and next;
        #print "This is $names[$child], Child number $child: $\n";
        work($child);
        $pm->finish($child); # pass an exit code to finish
    }
    print "Waiting for Children...\n";
    show_progress();
    $pm->wait_all_children;
    $now = time - $now;
    printf("\n\nTotal run time: %02d:%02d:%02d\n\n", int($now / 3600), int(($now % 3600) / 60), int($now % 60));
    print "Everybody done!\n";


    #==============================
    # real work of child process
    #==============================
    sub work {
        my $child = shift;

        my $total = int(rand(20)) + 5;
        foreach (1..$total) {
            select(undef, undef, undef, 0.2);
            sysopen (FIFO_W, $fpath, O_WRONLY) or die "can't write $fpath: $!";
            print FIFO_W "child:$child,processed:$_,total:$total\n";
            close FIFO_W;
        }

        sysopen (FIFO_W, $fpath, O_WRONLY) or die "can't write $fpath: $!";
        print FIFO_W "$child over\n";
        close FIFO_W;
    }


    #==================================================
    # receive progress data from child and display them
    #==================================================
    sub show_progress {
        while ($remain_child_process) {
            die "Pipe file disappeared" unless -p $fpath;
            sysopen (FIFO_R, $fpath, O_RDONLY) or die "can't read $fpath: $!";
            while(my $m = <FIFO_R>) {
                if ($m =~ m/over/) {
                    -- $remain_child_process;
                }
                else {
                    #print $m;
                    my ($child, $processed, $total) = $m =~ m/child:(\w+),processed:(\d+),total:(\d+)/;
                    $childs->{$child}->{processed} = $processed;
                    $childs->{$child}->{total} = $total;
                    proc_bar($childs);
                }
            }
            close FIFO_R;
        }
        $terminal->Tgoto('cm', 0, 5+2*@names, *STDOUT); #move cursor to bottom of screen
    }

    #=====================================
    # indicate the progress of comparation
    #=====================================
    sub proc_bar{
        my $childs = shift;
        local $| = 1;

        $terminal->Tgoto('sc', undef, undef, *STDOUT); #save cursor
        for my $c (sort keys %$childs) {
            my $i = $childs->{$c}->{processed};
            my $n = $childs->{$c}->{total};
            my $name = $childs->{$c}->{name};
            print "\r\033[36mchild: $c($name) [\033[33m".("#" x int(($i/$n)*50)).(" " x (50 - int(($i/$n)*50)))."\033[36m]";
            printf("%2.1f%%\033[0m\n",$i/$n*100);
        }
        $terminal->Tgoto('rc', undef, undef, *STDOUT); #restore cursor

        local $| = 0;
    }

 

你可能感兴趣的:(Perl 多进程进度条)