lollol Posté(e) le 8 avril 2013 Partager Posté(e) le 8 avril 2013 Salut, Pour monitorer des parametres de ma piscine, j'ai un automate, qui envoie des données a un convertisseur RS232 vers Wifi. J'accede aux données en envoyant une requete UDP de facon reguliere, et je les stocke sur une db mySQL (clef primaire, date et heure). J'ai voulu faire un script qui demarre et tourne en boucle sur le synology. J'utilise du Perl. Le script et sa procedure de lancement et d'arret semblent bien fonctionner. Le probleme c'est que Voila le script mapiscine.pl pour info (c'est pour communiquer avec un Crouzet Millenium, si ca vous interesse) : #!/opt/bin/perl use strict; use POSIX qw(strftime); use IO::Socket::INET; use DBI; use sigtrap 'handler' => &sigtrap, 'HUP', 'INT','ABRT','QUIT','TERM'; my ($socket,$data,$dbh,$t_dt,$query,$sth,$temp_air,$temp_eau,$press_filtr,$tps_filtr,$tps_robot,$filtr_state,@data_table,$flags); open(FH,">>logmapiscine"); print FH "debutn"; sleep(60); # Creation du socket UDP $socket=new IO::Socket::INET ( PeerAddr=>'192.168.1.254:55555', LocalPort => '55555', Proto=>'udp' ) or die "Erreur creation du socket UDPn"; print FH "socket creen"; #Connexion a la DB $dbh = DBI->connect("DBI:mysql:database=db_mapiscine;host=localhost", "root", "pouet", {AutoCommit => 1}) or die "Connexion impossible a la BDDn"; $dbh->{mysql_auto_reconnect} = 1; print FH "db connecteen"; #init Millenium $data=":010300006D00018Ern"; $socket->send($data); $data=<$socket>; print FH "mill initn"; #preparation requete insertion donnee $query = <<"SQL"; INSERT INTO `db_mapiscine`.`table_mapiscine` (`date_time`, `temp_air`, `temp_eau`, `press_filtr`, `tps_filtr`, `tps_robot`, `filtr_state`) VALUES (?,?,?,?,?,?,?); SQL $sth = $dbh->prepare($query) or die "Erreur preparation"; print FH "req prepareen"; while(1) { #request data $data=":04030000FF1810D2rn"; $socket->send($data); print FH "data envoyeesn"; #read operation $data=<$socket>; print FH "data recup $datan"; #Parse data $data=~ s/^.......//; $data=~ s/...$//; $data =~s/(.)/sprintf("%X ",ord($1) & 0x7F)/eg; $data =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; @data_table = split(/ /,$data); $t_dt=strftime('%Y-%m-%d %H:%M:%S',localtime); $temp_eau=hex($data_table[0].$data_table[1].$data_table[2].$data_table[3])/10; $temp_air=hex($data_table[8].$data_table[9].$data_table[10].$data_table[11])/10; $press_filtr=hex($data_table[16].$data_table[17].$data_table[18].$data_table[19])/100; $tps_filtr=hex($data_table[4].$data_table[5].$data_table[6].$data_table[7]); $tps_robot=hex($data_table[12].$data_table[13].$data_table[14].$data_table[15])/100; $flags=$data_table[20].$data_table[21].$data_table[22].$data_table[23]; $filtr_state=($flags & 0x1) ? 1 : 0; print FH "$t_dt $temp_airn"; $sth->execute($t_dt,$temp_air,$temp_eau,$press_filtr,$tps_filtr,$tps_robot,$filtr_state) or die "Erreur execution"; print FH "requete executeen"; sleep(30); print FH "fin bouclen"; } sub sigtrap(){ print FH "inter detectn"; $dbh->disconnect(); $socket->close(); close(FH); print FH "tout ferme intern"; exit(1); } Voila le script lancemapiscine.sh dans /usr/local/etc/rc.d qui assure le lancement du script : #!/bin/sh case "$1" in start) ((perl /usr/local/etc/mapiscine.pl) & echo $! > /var/run/mapiscine.pid &) ;; stop) kill `cat /var/run/mapiscine.pid` rm -f /var/run/mapiscine.pid ;; *) echo "Usage: `basename $0` {start|stop}" >&2 exit 64 ;; esac exit 0 Mon premier souci est que je n'arrive pas a logger quoi que ce soit. J'ai tenté de mettre exec >/tmp/monscript.log 2>&1 au debut de mon script shell... Niet! Idem comme vous pouvez le voir dans le script perl (ecriture dans un fichier des print). En fait çà amrche quand je lance le script manuellement via putty, mais quand je redemarre le NAS (pour simuler le fonctionnement reel) le script ne cree pas les fichiers de log... Je sais a quelle heure ca plante uniquement a cause de la derniere entrée de la database MySQL. Quand le script plante, il reste malgré tout dans top, mais la db ne s'increment plus. merci pour votre aide. 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 8 avril 2013 Partager Posté(e) le 8 avril 2013 (modifié) Lancé au démarrage (tu ne nous a pas dit comment mais ça ne change fondamentalement pas grand chose) l’environnement est minimum, et c'est le perl syno ("/usr/bin/perl", qui m'a souvent provoqué des problèmes louches) et pas celui d'optware qui va être utilisé. Pour forcer l'utilisation du perl optware: mettre le bon PATH *dans* le script (PATH=/opt/bin:/bin:/usr/bin) S'assurer aussi que le script est lancé *apres* que le "mount -bind" de "/opt" soit effectué (démarrage optware). Egalement, il est fort possible que la base de données ne soit pas encore démarrée lorsque le script est lancé au boot. Sinon, pour comprendre pourquoi le log ne se créée pas, faudrait que tu explique quelle méthode tu utilises pour le démarrage auto du script. Modifié le 8 avril 2013 par CoolRaoul 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 8 avril 2013 Auteur Partager Posté(e) le 8 avril 2013 merci pour ta reponse. Ben pour lancer mon script j'utilise le script lancemapiscine.sh présenté au dessus et mis dans /usr/local/etc/rc.d . Le script se lance bien au demarrage, je le vois bien incrementer ma BDD. Il ne doit donc pas se lancer trop tot (grace au sleep(60) dans le perl). Le probleme c'est qu'il semble ne plus tourner au bout de quelques heures... Et du coup j'aimerai logger çà. 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 8 avril 2013 Partager Posté(e) le 8 avril 2013 (modifié) merci pour ta reponse. Ben pour lancer mon script j'utilise le script lancemapiscine.sh présenté au dessus et mis dans /usr/local/etc/rc.d . Le script se lance bien au demarrage, je le vois bien incrementer ma BDD. Il ne doit donc pas se lancer trop tot (grace au sleep(60) dans le perl). Le probleme c'est qu'il semble ne plus tourner au bout de quelques heures... Et du coup j'aimerai logger çà. En tout cas commence par mettre la ligne PATH en début du script shell pour utiliser le perl optware et pas le perl syno (comme j'ai déja dit, celui-la m'a fait des trucs franchement étranges). Autre chose, je trouve la ligne: ((perl /usr/local/etc/mapiscine.pl) & echo $! > /var/run/mapiscine.pid &) un peu tarabiscotée avec tout ces "&" et ces sous-shells imbriqués. Je ferai comme cela plutôt (et ainsi plus besoin de "/opt/bin" dans le PATH): /usr/local/etc/mapiscine.pl <&- & # pourquoi pas /usr/local/bin ? echo $! > /var/run/mapiscine.pid (Pas oublier le chmod +x de "/usr/local/etc/mapiscine.pl") Dernière remarque, dans le perl tu fais: open(FH,">>logmapiscine"); Sans savoir quel est le répertoire courant, puisque ni le script shell ni le script perl de fait de "cd", ajouter un "cd /tmp" dans le shell ne peut pas faire de mal sinon tu n'est pas maitre de la localisation du fichier "logmapiscine" ***EDIT*** et essaie de remettre la ligne "exec" pour voir Modifié le 8 avril 2013 par CoolRaoul 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 8 avril 2013 Auteur Partager Posté(e) le 8 avril 2013 #!/bin/sh PATH=/opt/bin:/bin:/usr/bin cd /tmp exec >/tmp/monscript.log 2>&1 case "$1" in start) /usr/local/bin/mapiscine.pl <&- & echo $! > /var/run/mapiscine.pid ;; stop) kill `cat /var/run/mapiscine.pid` rm -f /var/run/mapiscine.pid ;; *) echo "Usage: `basename $0` {start|stop}" >&2 exit 64 ;; esac exit 0 Voila le script modifié selon tes conseils! Je redemarre le NAS et je te dis ce qu'il me fais. En tous cas merci de tes precieuses infos. franchement j'apprend des trucs!! 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 8 avril 2013 Partager Posté(e) le 8 avril 2013 (modifié) /usr/local/bin/mapiscine.pl <&- & Bien entendu, tu n'as pas oublié de déplacer "mapiscine.pl" dans /usr/local/bin au passage? Modifié le 8 avril 2013 par CoolRaoul 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 8 avril 2013 Auteur Partager Posté(e) le 8 avril 2013 (modifié) non non je l'ai bien déplacé, en fait je ne savais pas trop ou le mettre, merci de m'avoir aiguillé! Alors le script se lance bien je le vois dans top (8850 1 root S 9012 1.7 0.0 /opt/bin/perl /usr/local/bin/mapiscine.pl) , les fichiers logs sont bien créées dans le /tmp (logmapiscine et monscript.log). Ma db s'increment bien. Par contre les 2 fichiers de log font 0 en taille et sont vide quand je fais un cat dessus. Je pense que le log du script sh n'a rien a dire pour le moment, et que celui du perl est actualisé quand je le ferme ( close(FH) dans l'interruption signal). edit : ok verifié, le logmapiscine se rempli bien lorsque je fais un lancemapiscine.sh stop. Je verrai bien si ca plante et la je pourrais diagnostiquer vu que j'aurais les logs! Modifié le 8 avril 2013 par lollol 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 8 avril 2013 Partager Posté(e) le 8 avril 2013 Bon, on a bien avancé alors. 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 8 avril 2013 Auteur Partager Posté(e) le 8 avril 2013 (modifié) je pense que j'aurais le plantage d'ici demain, je reposterai les logs ici, avec je l'espere un debut d'explication de ma part. merci pour le coup de main Modifié le 8 avril 2013 par lollol 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 9 avril 2013 Auteur Partager Posté(e) le 9 avril 2013 (modifié) Voila les logs : fin boucle data envoyees data recup :0´03±0006²000²003²006´0063000¸003·003²±B 2013-04-09 07:46:51 5 requete executee fin boucle data envoyees data recup :0´03±0006²000²003²006´0063000¸003·003²±B 2013-04-09 07:47:22 5 requete executee fin boucle data envoyees data recup :0´03±0006²000²003²006´0063000¸003·003²±B 2013-04-09 07:47:53 5 requete executee fin boucle data envoyees >> dernière étape du script avant plantage inter detect >> moi qui arrête le script planté Donc je pense que le script au bout d'un moment envoie les data par protocole UDP, mais ne reçoit jamais de réponse de la part du pont wifi/RS232 (le paquet se perd ou je ne sais quoi, c'est l’inconvénient d'UDP je crois), et donc attend indéfiniment qu'il reçoive quelque chose. Je pensais modifier mon script perl pour qu'il refasse une requête si il ne reçoit pas les datas au bout de 1 ou 2 secondes... Je ne sais pas par contre comment faire pour passer la ligne $data=<$socket>; si elle ne reçoit pas de données... Modifié le 9 avril 2013 par lollol 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 9 avril 2013 Partager Posté(e) le 9 avril 2013 Je pensais modifier mon script perl pour qu'il refasse une requête si il ne reçoit pas les datas au bout de 1 ou 2 secondes... Je ne sais pas par contre comment faire pour passer la ligne $data=<$socket>; si elle ne reçoit pas de données... Je t'ai trouvé ça: http://stackoverflow.com/questions/4517034/perl-set-read-timeout-in-client-socket il y a peut-être des solutions plus élégantes, mais si ça marche après tout ... 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 9 avril 2013 Auteur Partager Posté(e) le 9 avril 2013 (modifié) ok merci de ton aide, mais la sur le coup ce soir j'ai pas trop capté leur idée de signal... visiblement il y a une fonction timeout mais celle -ci est désactivée dans IO::Socket....... Je m'y pencherai ce WE pour implémentation, ou alors je passerai en TCP. Modifié le 9 avril 2013 par lollol 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
PiwiLAbruti Posté(e) le 10 avril 2013 Partager Posté(e) le 10 avril 2013 Question bête : l'hibernation du NAS est bien désactivée ? 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 10 avril 2013 Partager Posté(e) le 10 avril 2013 (modifié) ok merci de ton aide, mais la sur le coup ce soir j'ai pas trop capté leur idée de signal... visiblement il y a une fonction timeout mais celle -ci est désactivée dans IO::Socket....... Je m'y pencherai ce WE pour implémentation, ou alors je passerai en TCP. Le code est relativement simple, et indépendant des fonctionnalités de IO::Socket. Le bloc "eval" positionne un "watchdog" local autour de la fonction "sysread" La sortie du bloc va se faire dès que l'une des conditions suivantes est réalisée: le timer à expiré (valeur en secondes de la variable "timeout") la lecture du socket à réussi la lecture du socket à échoué sur une autre erreur Suffit donc de faire la meme chose en remplaçant ta ligne "$data=<$socket>;" grosso modo par quelque chose du genre de: my $timeout=2; # secondes eval { local $SIG{ALRM} = sub { die "alarmn" }; alarm $timeout; $data=<$socket>; alarm 0; }; if ($@) { die unless $@ eq "alarmn"; # autre erreur # sinon ici timeout atteint .... } else { # ici lecture socket reussie si $data != "" .... } Modifié le 10 avril 2013 par CoolRaoul 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 10 avril 2013 Partager Posté(e) le 10 avril 2013 Solution, à mon avis plus élégante, utilisant IO::Select Ajouter au début du script: use IO::Select; my $timeout=2; # secondes puis juste après l'initialisation du socket: my $selection = IO::Select->new($socket); Enfin, code de lecture de la socket avec timeout: if (my @handles = $selection->can_read($timeout)) { # des données sont arrivées sur le socket my $handle=shift(@handles); $data = <$handle>; } else { # si on arrive ici, alors la lecture du socket # n'a rien reçu avant l'expiration du timeout # a toi de décider comment traiter le cas.. } 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
CoolRaoul Posté(e) le 10 avril 2013 Partager Posté(e) le 10 avril 2013 Si on prend en compte l'ensemble du code demande/réponse on aboutit à do { $query=":04030000FF1810D2rn"; $socket->send($query); print FH "demande envoyéen"; if (my @handles = $selection->can_read($timeout)) { # des données sont arrivées sur le socket my $handle=shift(@handles); $data = <$handle>; }; } until ($data); (reste à améliorer le traitement des erreurs, et éventuellement un compte de "retries" pour ne pas partir dans une boucle infinie en cas de défaillance du convertisseur RS232) 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 10 avril 2013 Auteur Partager Posté(e) le 10 avril 2013 vraiment très sympa de m'avoir prémâché le boulot je ne m’attendais pas a tant! :D j'ai donc implémenté le script, je redémarre le NAS et je log toute la nuit pour voir. Ah oui, je viens de désactiver l'hibernation des disques au bout de 30 minutes, même si je pense que vu que le script tournait en boucle ac ne devait rien changer (il plantait au bout de 5 - 6h en plus). 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
lollol Posté(e) le 11 avril 2013 Auteur Partager Posté(e) le 11 avril 2013 (modifié) bon ben il tourne toujours ce soir, pas de plantages, merci a toi CoolRaoul Voici la dernière version : #!/opt/bin/perl use strict; use POSIX qw(strftime); use IO::Socket::INET; use IO::Select; use DBI; use sigtrap 'handler' => &sigtrap, 'HUP', 'INT','ABRT','QUIT','TERM'; my ($selection,$timeout,$socket,$data,$dbh,$t_dt,$query,$sth,$temp_air,$temp_eau,$press_filtr,$tps_filtr,$tps_robot,$filtr_state,@data_table,$flags); $timeout=2; open(FH,">>logmapiscine"); print FH "debutn"; sleep(60); # Creation du socket UDP $socket=new IO::Socket::INET ( PeerAddr=>'192.168.1.254:55555', LocalPort => '55555', Proto=>'udp' ) or die "Erreur creation du socket UDPn"; print FH "socket creen"; $selection = IO::Select->new($socket); #Connexion a la DB $dbh = DBI->connect("DBI:mysql:database=db_mapiscine;host=localhost", "root", "pouet", {AutoCommit => 1}) or die "Connexion impossible a la BDDn"; $dbh->{mysql_auto_reconnect} = 1; print FH "db connecteen"; #init Millenium $data=":010300006D00018Ern"; $socket->send($data); $data=<$socket>; print FH "mill initn"; #preparation requete insertion donnee $query = <<"SQL"; INSERT INTO `db_mapiscine`.`table_mapiscine` (`date_time`, `temp_air`, `temp_eau`, `press_filtr`, `tps_filtr`, `tps_robot`, `filtr_state`) VALUES (?,?,?,?,?,?,?); SQL $sth = $dbh->prepare($query) or die "Erreur preparation"; print FH "req prepareen"; while(1) { do { $query=":04030000FF1810D2rn"; $socket->send($query); print FH "demande envoyéen"; if (my @handles = $selection->can_read($timeout)) { # des données sont arrivées sur le socket my $handle=shift(@handles); $data = <$handle>; }; } until ($data); #Parse data $data=~ s/^.......//; $data=~ s/...$//; $data =~s/(.)/sprintf("%X ",ord($1) & 0x7F)/eg; $data =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; @data_table = split(/ /,$data); $t_dt=strftime('%Y-%m-%d %H:%M:%S',localtime); $temp_eau=hex($data_table[0].$data_table[1].$data_table[2].$data_table[3])/10; $temp_air=hex($data_table[8].$data_table[9].$data_table[10].$data_table[11])/10; $press_filtr=hex($data_table[16].$data_table[17].$data_table[18].$data_table[19])/100; $tps_filtr=hex($data_table[4].$data_table[5].$data_table[6].$data_table[7]); $tps_robot=hex($data_table[12].$data_table[13].$data_table[14].$data_table[15])/100; $flags=$data_table[20].$data_table[21].$data_table[22].$data_table[23]; $filtr_state=($flags & 0x1) ? 1 : 0; print FH "$t_dt $temp_airn"; $sth->execute($t_dt,$temp_air,$temp_eau,$press_filtr,$tps_filtr,$tps_robot,$filtr_state) or die "Erreur execution"; print FH "requete executeen"; sleep(30); print FH "fin bouclen"; } sub sigtrap(){ print FH "inter detectn"; $dbh->disconnect(); $socket->close(); close(FH); print FH "tout ferme intern"; exit(1); } Modifié le 11 avril 2013 par lollol 0 Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Messages recommandés
Rejoindre la conversation
Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.