Thread watchdog bei einer while-Schleife (20 answers)
Opened by perlensammler22 at 2015-09-22 07:29

Linuxer
 2015-09-24 00:01
#182361 #182361
User since
2006-01-27
3891 Artikel
HausmeisterIn

user image
Hi,

ich wollt es selber mal ausprobieren...

Zunächst ein simples Skript, um alle X Sekunden einen Output zu generieren:

datastream (3.6kb):

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#! /usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;

$| = 1;             # unbuffered STDOUT

GetOptions(
    \my %OPT,
    'interval=i',
) or exit 255;

die "(E) No interval specified.\n"  unless $OPT{interval};


while ( 1 ) {
    print scalar(localtime), "\n";

    sleep $OPT{interval};
}

__END__



Dann ein Skript, welches über die Argumente genannt bekommt, von welchem Programm es lesen soll und wie lange es dauern soll, bis ein Timeout vorliegt:

readstream (9.0kb):

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#! /usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;

$| = 1;             # unbuffered STDOUT


# save command and cmdline arguments for later re-use
# because GetOptions modifies @ARGV
my @cmdline = ( $0, @ARGV );


GetOptions(
    \my %OPT,
    'timeout=i',
) or exit 255;

die "(E) No timeout specified.\n"   unless $OPT{timeout};

my @command = @ARGV;


my $pid = open my $pipe, '-|', @command
    or die "(E) Could not open pipe to command '@command': $!";

print "pid $pid : @command\n";

while ( 1 ) {
    my $line;

    # read from $pipe; must be successful within $OPT{timeout} seconds
    eval {
        local $SIG{ALRM} = sub { die "alarm\n"; };
        alarm $OPT{timeout};
        $line = <$pipe>;
        alarm 0;
    };

    # timeout exceeded
    if  ( $@ ) {
        die "(E) error in alarm...\n"   if $@ ne "alarm\n";
        print "ALARM received!\n";
        exec( @cmdline ) or die "(E) Could not re-execute myself: $!";
    }
    # just in time
    else {
        print "READ: $line";
    }
}

__END__



Der Aufruf dann als:
Code: (dl )
./readstream --timeout 3 -- ./datastream --interval 5

Mit -- endet die Optionsliste für readstream; alles was danach kommt, wird für das auszuführende Kommando verwendet; hier also ./datastream --interval 5.
datastream soll nur alle 5 Sekunden eine Ausgabe liefern, und readstream soll schon nach 3 Sekunden einen Timeout melden.

Resultat:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
pid 4964 : ./datastream -int 5
READ: Wed Sep 23 23:56:03 2015
ALARM received!
pid 4965 : ./datastream -int 5
READ: Wed Sep 23 23:56:06 2015
ALARM received!
pid 4966 : ./datastream -int 5
READ: Wed Sep 23 23:56:09 2015
ALARM received!
pid 4967 : ./datastream -int 5
READ: Wed Sep 23 23:56:12 2015
^C


Alle 5 Sekunden kommt die Ausgabe von datastream; aber schon nach 3 Sekunden meldet sich der alarm mit der Timeout Meldung. Mit der exec()-Zeile wird dann das Skript selber nochmal aufgerufen (man beachte die steigende PID für datastream bei den Ausgaben). Die PID für readstream bleibt dabei dieselbe (beachte Perldoc:perlfunc exec).
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!

View full thread watchdog bei einer while-Schleife