Wie erstelle ich eine 'Bitte Warten'-Seite?

Inhalt:

Problem

Ein CGI-Skript führt einen langwierigen Prozess aus, aber der Benutzer soll solange eine 'Bitte Warten'-Seite sehen.

Lösung

Man forkt den Prozess und macht einen Redirect auf ein Skript, dass prüft, ob der Prozess zu ende ist. Wenn ja, zeigt es das Ergebnis an, wenn nicht, macht es einen meta-refresh auf sich selbst.

Folgendes Skript veranschaulicht dies mit einer etwas sinnlosen Funktion, die aber das Prinzip zeigt.

#!/usr/bin/perl

# background.pl
# Aufruf: http://server/background.pl?w=create;count=5

use strict;
use warnings;
use CGI;
use Fcntl qw(:flock);

my $cgi = CGI->new;
my $url = "http://server/background.pl";
                                                         
my $w = $cgi->param('w') || 'show';
if ($w eq 'show') {
    show($cgi);
}
elsif ($w eq 'create') {
    create($cgi);
}

sub create {
    my ($cgi) = @_;
    my $val = $cgi->param('count') || 5;
    if ($val =~ tr/0-9//c or $val > 10) {
        $val = 5;
    }
    my $id = time() . $$;
    my $filename = "background.id$id";
    $SIG{CHLD} = 'IGNORE';
    if (my $pid = fork) {
        # parent
        print $cgi->redirect("/background.pl?w=show;id=$id");
        close STDOUT;
        close STDERR;
        close STDIN;
        exit;
    }
    else {
        open my $fh, ">", $filename or die $!;
        flock $fh, LOCK_EX;
        close STDOUT;
        close STDERR;
        close STDIN;
        for my $i (1 .. $val) {
            print $fh "$i\n";
            sleep 2;
        }
        close $fh;
        exit;
    }
}

sub show {
    my ($cgi) = @_;
    my $id = $cgi->param('id') || '';
    $id =~ tr/0-9//cd;
    print $cgi->header;
    if (length $id > 20) {
        print $cgi->start_html;
        print "too long";
    }
    else {
        my $filename = "background.id$id";
        my $meta = $cgi->start_html(
            my $meta_refresh =
            -head => $cgi->meta(
                {
                    -http_equiv => 'refresh',
                    -content    => "2; $url?w=show;id=$id",
                }
            ));
        if (open my $fh, "<", $filename) {
            my $lock = flock $fh, LOCK_EX|LOCK_NB;
            if ($lock) {
                # success, got lock
                my $output = do { local $/; <$fh> };
                print "Result: $output";
            }
            else {
                print $meta;
                print "Not finished";
            }
            close $fh;
        }
        else {
            print $meta;
            print "File not yet created";
        }
    }
    print $cgi->end_html;
}

Ergänzungen, Kommentare

Kommentare werden am besten in folgender Form vorgenommen, damit sie im Inhaltsverzeichnis angezeigt werden (natürlich ohne das <verbatim>):
---+++ Main.??? - 14 Jul 2003 - Betreff

UtilFaqSubForm edit

Titel Wie erstelle ich eine 'Bitte Warten'-Seite?
Autor TinaMueller
Bereich FaqCGI
Tags fork cgi
Topic revision: 2008-03-01, TinaMueller
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.