+#Fichier de conf du muxdaemon
+#
+#Ce démon permet de gérer plusieurs programmes clients (comme des parseurs de
+#mail, de log), en les lançant au moment opportun. Il permet de plus de
+#s'affranchir de certains problèmes de sécu, pour les mails notamment, car le
+#programme client peut tourner en n'importe quel utilisateur, les mails lui
+#étant pipés par ce démon (qui par conséquent doit tourner en mode privilégié
+#Le lancement des différents clients se fait selon plusieurs critères :
+# - charge de la machine
+# - "réentrance" du client (peut-on en avoir plusieurs instances en cours d'éxécution ?)
+# - priorité de 1 à 100, le démon essai de lancer le client de
+# priorité 100 cent fois plus souvent que celui de priorité 1
+# - temps minium entre deux éxécutions d'un client
+#
+
+#Le fonctionnement du démon est le suivant :
+#toutes les active_poll secondes, le démon filtre la liste des clients de
+#manière à ne conserver que les runnables. Si la charge est trop élevé pour
+#tous les clients, le démon attand sleep_poll secondes avant de repasser en
+#active_poll.
+#
+
+#Scheduler :
+#Il est ultra basique.Il essaie de respecter les priorités, mais si un programme
+#X de haute priorité est lancé, qu'il dure plus longtemps qu'un client Y de
+#faible priorité, et que la charge et le nombre total de clients autorisés sont
+#tels que Y peut être lancé, alors il l'est. Si le processus se répète, Y
+#peut-être lancé beaucoup plus souvent que X. Mais dès que X est runnable, il
+#est lancé. Les schedule consiste donc à maximiser le nombre de clients en cours
+#d'éxécution, tout en respectant les priorités.
+#
+
+#Pour les boites maildir :
+#actuellement, les fichier sont lus dans le répertoire new/ pipés vers le
+#client, puis déplacés dans cur/
+
+
#Cette commande doit renvoyer la charge
ldcmd = "cat /proc/loadavg | sed 's/^\([^ ]* \).*$/\1/'"
-#error_log
+#Fichier de log
error_log = "/home/julien/toto"
-#Poll every 60 seconds
-#Active poll : Time to wait between 2 launches in sec
+#Active poll : Temps d'attente entre deux lancements en mode actif
active_poll = 0
#Time to wait when load is too high for any client in sec
-sleep_poll = 60
+sleep_poll = 10
-#Nombre max de client à ne pas dépasser simultanément
-max_client = 1
+#Nombre total de clients à ne pas dépasser simultanément
+max_client = 15
<client erreurs>
#Charge au dessus de laquelle ce programme ne doit plus être lancé
- max_load=0.3
+ max_load=0.4
#Mbox
#Si mbox existe, des lots de nb_mails y sont lus et pipés dans command
#si mbox termine par un "/", c'est une boite maildir
- #Pas encore implémenté
+ #Implémenté pour les boites maildir uniquement
mbox=/var/mail/xorg-errors/
- #nombre de mails à traité ((1 command executée par mail)
- nb_mails=50
- #Command to launch (datas are piped in it if mbox defined)
- command="cat"
+ #nombre de mails à traité ((1 commande executée par mail)
+ nb_mails=5
+ #Command to launch (datas are piped in it if maildir mbox defined)
+ command="cat >/dev/null"
#Peut-on lancer plusieurs instances de ce prog simultanément ? yes or no
allow_many=no
#Priority relative aux autres de 1 à 100
#Lancer le prog en tant que :
run_as_user=julien
run_as_group=julien
- #Temps minimum entre deux lancements d'un client en sec
+ #Temps minimum entre deux lancements de ce client en sec
min_schedule=0
</client>
<client toto>
- max_load=0.3
+ max_load=0.5
command="/bin/sleep 1"
- allow_many=no
+ allow_many=yes
priority=99
</client>
<client titi>
- max_load=0.3
+ max_load=0.5
command="/bin/sleep 3"
- allow_many=no
+ allow_many=yes
priority=57
run_as_user=jb
run_as_group=jb
</client>
<client tutu>
- max_load=0.3
+ max_load=0.5
command="/bin/sleep 2"
- allow_many=no
+ allow_many=yes
priority=69
</client>
my %launches;
my %ratio_launch_prio;
my %last_schedule;
-my $priority_ref = "";
###############
## Functions ##
sub debug_msg(#){
- my $msg=shift;
- if ($debug == 1){
- print STDERR $msg;
- }
+ my $text=shift;
+ print STDERR $text unless ($debug == 0);
}
}
if ($opts{'d'}){
+ print STDERR "Running in debug mode ...\n";
$debug = 1;
}else{
$debug = 0;
}
-
}
-sub init_launches(){
- my $min_priority=100;
+#init useful variables for scheduler
+sub init_sched(){
foreach my $arg (keys %{$conf{'client'}}){
$launches{"$arg"}=0;
$ratio_launch_prio{"$arg"}=0;
+ $last_schedule{"$arg"}=0;
}
}
-
-sub check_conf(){
+#check configuration file
+sub check_conf{
+ &debug_msg("Salut\n");
print STDERR "Checking configuration file for wrong user/groups, schedules, ....\n";
foreach my $arg (keys %{$conf{'client'}}){
#La conf du client courant
}
}
-
+
+#make the program run in daemon mode
sub daemonize {
print STDERR "Forking ... \n";
chdir '/' or die "Can't chdir to /: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
- umask 0;
+ #umask 0;
&debug_msg("Daemon started\n");
}
+
+#returns current load or any good value
sub get_load {
my $load = `$conf{"ldcmd"}`;
- chop($load);
- #&debug_msg("$load\n");
+ chomp($load);
return $load;
}
#Return the list of client for which max_load is => ld
+#param : load
sub get_possible_client(#){
my $ld=shift;
my @list=();
- #&debug_msg("get_possible_client, load = $ld\n");
+
foreach my $arg (keys %{$conf{'client'}}){
- #&debug_msg("get_possible_client : Trying client $arg :");
my $hash = ${$conf{'client'}}{$arg};
if (${$hash}{'max_load'} >= $ld){
- #&debug_msg("max_load = ".${$hash}{'max_load'}." => in\n");
push(@list,$arg);
- }else{
- #&debug_msg("max_load = ".${$hash}{'max_load'}." => out\n");
}
}
return \@list;
#Sends mail on the input of the command (pipe)
sub send_data(#){
- my $client=shift;
- if (${${$conf{'client'}}{$client}}{'mbox'} =~ /\/$/){
- &debug_msg("Sending datas for ${${$conf{'client'}}{$client}}{'mbox'}\n");
- my @list=`ls -1 ${${$conf{'client'}}{$client}}{'mbox'}/new | head -n ${${$conf{'client'}}{$client}}{'nb_mails'}`;
+ my $client = shift;
+ my $hash = ${$conf{'client'}}{$client};
+ if (${$hash}{'mbox'} =~ /\/$/){ #ok, maildir format
+ my $path = "${$hash}{'mbox'}";
+ $path =~ s/\/$//igo;
+ &debug_msg("Sending datas for ${$hash}{'mbox'}\n");
+ my @list=`ls -1 $path/new | head -n ${$hash}{'nb_mails'}`;
if ($#list >= 0){
#Send files, one by one
foreach my $fich (@list){
+ chomp($fich);
&debug_msg("File : $fich\n");
if (my $pid = open(CHILD, "|-")) {
CHILD->autoflush(1);
- &debug_msg("Parent Pid $$\n");
- if (open(DATA,"<${${$conf{'client'}}{$client}}{'mbox'}/new/$fich")){
+ if (open(DATA,"<$path/new/$fich")){
while (my $line=<DATA>){
print CHILD "$line";
- #&debug_msg("Sending : $line");
}
close(DATA);
+ &debug_msg("$path/new/$fich -> $path/cur/$fich ... ");
+ if (rename("$path/new/$fich","$path/cur/$fich")){
+ &debug_msg("ok\n");
+ }else{
+ print STDERR "Error moving $path/new/$fich, keeped : $!\n";
+ }
}else{
- &debug_msg("Error opening ${${$conf{'client'}}{$client}}{'mbox'}/new/$fich : $!\n");
+ print STDERR "Error opening $path/new/$fich : $!\n";
exit(1);
}
close(CHILD);
- #unlink("${${$conf{'client'}}{$client}}{'mbox'}/new/$fich");
} else {
die "cannot fork: $!" unless defined $pid;
&change_uid_gid("$client");
- &debug_msg("Executing ${${$conf{'client'}}{$client}}{'command'} .... \n");
- exec("${${$conf{'client'}}{$client}}{'command'}");
+ &debug_msg("Executing ${$hash}{'command'} .... \n");
+ exec("${$hash}{'command'}");
}
}
}else{
&debug_msg("done\n");
&debug_msg(" Restarting ...");
&init;
- &init_launches;
+ &init_sched;
&debug_msg("done\n");
}
$SIG{HUP}=\&sigHUP_handler;
&init();
-&init_launches();
&check_conf();
+&init_sched();
&daemonize();
&main_loop();