Thread befehl zu einer gegebenen zeit ausführen
(5 answers)
Opened by
fivefinger
at 2008-01-26 21:56
User since 2006-07-10
2611
Artikel
BenutzerIn
Wenn es als Userprozess laufen soll wäre ein Deamon nicht schlecht. Also ein Hintergundprozess der regelmäßig nach schaut, ob er eine Nachricht anzeigen soll.
So könnte es aussehen:
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
#!/usr/bin/perl
use strict; use warnings; use POSIX ":sys_wait_h";
my %conf=( alarm_file => 'alarm.conf', deamon_pid_file => 'alarm.pid', alarm_list=>[], verbose=>0 );
#print join('|',@ARGV).' --- '.(grep{$_=~/--nofork/}@ARGV)."\n";
# run as deamon if(0 < grep{$_=~/--deamon/}@ARGV) { $conf{verbose}=1 if(0 < grep{$_=~/--verbose/}@ARGV);
if(0 == grep{$_=~/--nofork/}@ARGV) { print "go to background.\n" if($conf{verbose}); exit if(fork); }
# go to background print "save pid to file $conf{deamon_pid_file}\n" if($conf{verbose}); my $msg=save_pid($conf{deamon_pid_file}); die "$msg\n" if($msg);
update_alarms(); # alarm_file neu laden wenn # das passende Signal über SysV-IPC # kommt $SIG{USR1}=\&update_alarms;
while(1) { my $now=time(); # aufgelaufenen Alarme ausgeben... while( @{$conf{alarm_list}}>0 && $conf{alarm_list}->[0]->{time} < $now) { my $alarm=shift(@{$conf{alarm_list}}); print "ALARM! ".localtime($now)."\n"; print <<"EOF"; TITEL: $alarm->{title} INALT: $alarm->{message}
EOF } # warte eine Sekunde sleep 1; } } # run as client else { my $title=''; my $time=0; my $message=''; for my $opt (@ARGV) { if($opt=~/--title=(.+)/) { $title=$1; } elsif($opt=~/--time=(.+)/) { $time=int($1); } elsif($opt=~/--message=(.+)/) { $message=$1; } elsif($opt=~/--verbose/) { $conf{verbose}=1; } else {die "Unknown option $opt\nusage:\n".usage();} }
my $now=time(); if($now>=$time) { print "alarmdate not in the future!\n"; exit; } print "append alarm to file $conf{alarm_file}\n" if($conf{verbose}); my $msg=append_alarm($conf{alarm_file},$title,$time,$message); warn $msg."\n" if($msg); print "load deamon pid file from file $conf{deamon_pid_file}\n" if($conf{verbose}); my $pid; ($msg,$pid)=load_pid($conf{deamon_pid_file}); die $msg."\n" if($msg); if(waitpid($pid,WNOHANG)==-1) { print "old deamon pid file $conf{deamon_pid_file}. No demon running?\n" if($conf{verbose}); } else { print "sendig alarm update IPC signal to $pid\n" if($conf{verbose}); server_reload($pid); } }
################################# ######### FUNKTIONEN ############ #################################
sub usage { return <<"EOF"; $0 [--deamon | --title, --time, --message] --deamon : run as deamon --title : set title of alarmmessage --message : set alarmmessage --time : set time when the message ist displayed --verbose : be verbose --nofork : deamon don't fork and go to background EOF #' }
############## ### SERVER ### ##############
sub save_pid { my $file=shift; open(my $fh, '>', $file) or return("Could not open $file ($!)"); print $fh $$; close($fh); return 0; }
sub load_alarms { my $file=shift; my $now=time(); my @alarm_dates; my @msg; open(my $fh, '<', $file) or return(["Could not open $file ($!)"],[]); my $cnt=0; while(my $line = <$fh>) { $cnt++; chomp($line);
# leere zeilen ignorieren; next if($line=~/^\s*$/); # kommentare ignorieren; next if($line=~/^\s*#/); # Zeile Parsen if($line=~/^\s*(.+?)\s*=\s*(\d+)\s*,\s*(.*?)$/) { my($title,$time,$message)=($1,$2,$3); push(@msg,"Alarm found in line $cnt"); #veraltete Alarme ignorieren if($time >= $now) { push( @alarm_dates, {title=>$title, time=>int($time), message=>$message} ); } else { push(@msg,"ignore old Alarm in Line $cnt"); } } else { push(@msg,"Could not parse Line $cnt !"); } } close($fh); return(\@msg,\@alarm_dates); }
sub sort_alarms() { $conf{alarm_list}=[sort{$a->{time} <=> $b->{time}}@{$conf{alarm_list}}]; }
sub update_alarms { print "load alarms from file $conf{alarm_file}\n" if($conf{verbose}); my ($msg,$alarm)=load_alarms($conf{alarm_file}); print join("\n",@$msg)."\n" if($conf{verbose}); $conf{alarm_list}=$alarm if(@$alarm >0); sort_alarms(); }
############## ### CLIENT ### ############## sub load_pid { my $file=shift; my $pid=0; open(my $fh, '<', $file) or return("Could not open $file ($!)",-1); $pid=int(<$fh>); close($fh); return('',$pid); }
sub append_alarm { my $file=shift; my $title=shift; my $time=shift; my $message=shift; open(my $fh, '>>', $file) or return("Could not open $file ($!)"); print $fh "$title=$time,$message\n"; close($fh); return 0; }
sub server_reload { my $deamon_pid=shift; kill('USR1',$deamon_pid); return 0; }
die "alarm.conf":
# Die liste mit den Alarmen # format: # test=1201439000,nur ein test test=1201440909,nur ein test test2=1201441556,noch ein test
In der "alarm.pid" steht nur die Prozessid des Deamon damit ich mit "kill" eine Nachricht schicken kann.
Das ist noch etwas unausgreift, da ich die datei mit den Alarmzeiten jwährend des lesens/schreiben nicht sperre, die Datei nicht von alten Alarmen säubere, den Deamonprozess nicht automatisch starte, wenn er nicht vorhanden ist, keine vernünftige Ausgabe mache, usw.
Aber grundsätzlich kann man es so machen.
View full thread befehl zu einer gegebenen zeit ausführen
|