Script shell en tant que démon ? [Shell / C] - Shell/Batch - Programmation
Marsh Posté le 05-10-2006 à 13:48:53
une solution pas forcément très propre mais facile à mettre en place (en attendant de faire mieux), c'est d'utiliser at :
tu ajoutes à la fin de ton script une ligne qui demande la réexécution du script un peu plus tard. genre 'at now + 1 hours < /chemin/vers/ton/script'
la première fois, tu lances le script à la main (ou automatiquement avec /etc/init.d). Ensuite, c'est le script lui-même qui programme sa propre réexécution un peu plus tard.
Marsh Posté le 05-10-2006 à 14:20:43
Bonjour,
A la base le script boucle à l'infini (sans doutes moins propre que ce que tu proposes). Il scan le rep, envoie les sms si il ya des fichiers dedans, attend xx secondes une fois le traitement fini (même chose si le dossier est vide).
Mon problème c'est de faire en sorte que mon script tourne en permanence, et qu'il ne meurt pas une fois que j'ai fermé le shell qui l'a lancé.
Il faudrait que je puisse le démarrer via un script dans /etc/init.d mais je n'y arrive pas. J'ai essayé avec un script qui ressemble à ça:
Code :
|
Mais ça ne fonctionne pas. Quand je lance "/etc/init.d/mon_script start" le bash me renvoie ceci:
Code :
|
D'où ma question sur la possibilité de lancer un script shell de cette facon (ce qui m'a l'air compromis vu qu'il semble attendre un fichier binaire...).
Marsh Posté le 05-10-2006 à 14:42:12
tieuma a écrit : Mon problème c'est de faire en sorte que mon script tourne en permanence, et qu'il ne meurt pas une fois que j'ai fermé le shell qui l'a lancé. |
tu peux utiliser nohup pour ça.
Je ne sais pas trop d'où vient l'erreur dans ton script init.d
Marsh Posté le 05-10-2006 à 15:37:51
Merci pour nohup, je ne connaissais pas
Ca fera l'affaire pour le moment mais il faudra que je trouve une solution pour que mon script init.d fonctionne (les SMS sont utilisés, en partie, pour les alertes nagios critiques , donc il faut que la commande soit lancée si redemarrage de la machine ou si le processus meurt).
Merci en tous cas pour ton aide.
Marsh Posté le 09-10-2006 à 15:13:57
Je up le sujet car j'ai encore un problème.
J'ai réussi à faire executer mon script au démarrage. Le problème est qu'il ne semble pas posseder les mêmes droits que lorsque je le lance en root. Le script appelle "gnokii" qui permet d'envoyer des sms via un gsm nokia. Le gsm est branché sur le port serie dont le fichier descripteur est "ttyS0".
Si je lance mon script dans un terminal, l'accès au GSM (au fichier ttyS0) est autorisé. Par contre le script lancé au demarrage se fait jeté.
Mon script est lancé au runlevel 5.
Une idée ? Merci.
Marsh Posté le 09-10-2006 à 15:41:02
A quel moment est lancé ton script ? Tu es sûr que tous les points de montage /dev/ttyS* ont déjà été créés à cette étape ?
Essaie de lancer ton script à la fin du boot (genre priorité 99) pour voir ce que ça donne...
Marsh Posté le 09-10-2006 à 17:50:23
Bonjour,
Finalement gnokii accède bien au fichier ttyS0. Le probleme venait du fait que je n'avais pas spécifié l'emplacelement du binaire gnokii dans mon script shell. Lorsque le script etait appelé lors du passage à init 5, le chemin utilisé etait /usr/bin/gnokii alors qu'en etant deja logué en root le chemin est /usr/local/bin/gnokii.
Maintenant j'ai un autre problème .
Lorsque je lance mon script de démarrage en root (/etc/init.d/smsgateway start & ), tout se passe comme prévu, le sms est envoyé. Si je repasse en init 3 puis en init 5 pour simuler le démarrage, tout se passe normalement, je vois mon processus gnokii se lancer, durer environ 30 et... rien. Pas de sms d'envoyer. Il doit y avoir une erreur pdt l'envoi du sms mais impossible de voir quoique ce soit.
Il faut que je redirige le log de gnokii vers un fichier pour savoir ce qui se passe.
Edit: apparemment, lorsque gnokii est lancé par mon script lui même lancé au runlevel 5, gnokii perd l'emplacement du fichier de conf et un timeout se produit lors de la recuperation du smsc
Marsh Posté le 10-10-2006 à 10:42:56
oui, mais il me semble que c'est spécifique à certaines distributions (debian et ses dérivées ?)
Je l'ai par exemple sur ma debian perso, mais pas sur la mandrake du boulot. Du coup, je ne savas pas si tieuma y a accès.
Marsh Posté le 11-10-2006 à 15:45:26
C'est bon, j'ai réussi à faire ce que je voulais (enfin presque...). Merci pour vos conseils.
Marsh Posté le 11-10-2006 à 23:35:37
Tout le monde a donné pas mal d'infos. Je vais essayer de résumer
tieuma a écrit : 1) Est-ce possible de créer un démon à partir dun script Shell ? |
Un démon c'est grosso-modo un programme qui tourne à l'infini et qui fait des trucs. Rien ne t'empêche de faire un "while true" dans un script et lancer ce script d'une façon ou d'une autre. Ce sera un démon.
tieuma a écrit : Javais également pensé utiliser « cron » pour lancer périodiquement mon script, le problème est que lenvoi de SMS (par gnokii) peut prendre du temps et donc il faut que je regarde si mon script est déjà en cours dexécution. Bref il faut que « cron » appelle un script qui surveille celui qui envoie les SMS et qui lappelle sil nest pas actif. Je naime pas trop cette solution et en plus je ne sais pas comment tester si mon script denvoi est actif (j'ai que "bash" ou "sh" comme nom dans la liste des processus, donc je ne vois pas trop comment être sur de tester le bon; je pourrai tester l'existence du processus « gnokii » mais il se peut aussi que le test se fasse pendant le scan du répertoire ou même entre 2 appels de « gnokii »). |
Dans l'absolu, rien n'empêche un programme de s'exécuter plusieurs fois en parallèle. Donc même si l'envoi du SMS prend du temps, rien n'interdit à priori de relancer une 2° instance du programme, celui-ci envoyant lui-aussi le SMS... sauf si le programme utilise une ressource unique de façon exclusive. Mais t'as raison, faire un 2° script pour détecter que le premier n'a pas déjà été lancé c'est un peu beaucoup sale.
En général, quand on veut faire un script exclusif, on lui fait créer un fichier particulier (dans "/tmp" par exemple) et détruire le fichier à la fin d'exécution. Et on place au début du script un test vérifiant si le fichier n'existe pas déjà. Ainsi si le programme est lancé 2 fois, la 2° instance détectant que le fichier existe déjà refuse de continuer.
tieuma a écrit : Enfin je pensais réécrire le script Shell en C pour pouvoir utilisé la méthode classique de lancement de démons (référencement dans /etc/init.d) |
Rien n'interdit de mettre dans "/etc/rc.d/init.d" un script shell. Mais si t'as envie de l'écrire en C...
tieuma a écrit : désolé japprends ) ? |
pas un pb. Le répertoire "/etc/rc.d/init.d" est conçu de façon bien précise. On lui place en "vrac" tous les scripts/programmes. Puis on va placer dans le répertoire "/etc/rc.d/rcN.d" ("N" étant le niveau de démarrage de la machine compris entre 0 et 6) un lien symbolique relié au script de "init.d". Cela permet
1) de relier le programme à plusieurs niveaux (on place un lien dans chaque "rcN.d" voulu)
2) malgré le fait que ce code puisse être appelé dans plusieurs niveaux, il n'y a qu'un seul source (si on veut le modifier par exemple)
Le nom du script est libre. En revanche, le nom du lien doit impérativement commencer par "S" ou "K". Au démarrage de la machine, le programme init balaye tous les "S" (comme "Start" ) de son niveau et les lance séquentiellement en y passant le mot "start". Et lors de l'arrêt, il exécute séquentiellement tous les "K" (comme "Kill" ) en y passant le paramètre "stop". A toi de faire en sorte que ton script/programme C prenne en compte ces 2 paramètres...
Et sinon, "nohup" signifie "nohang up" (pas de "main levée" ) et indique au shell de ne pas tuer le processus au cas où son père viendrait à mourir (comportement par défaut). Il est d'usage de l'associer au caractère "&" afin de pouvoir continuer à travailler pendant que le processus tourne.
Marsh Posté le 11-10-2006 à 23:52:21
Sve@r a écrit : Le nom du script est libre. En revanche, le nom du lien doit impérativement commencer par "S" ou "K". Au démarrage de la machine, le programme init balaye tous les "S" (comme "Start" ) de son niveau et les lance séquentiellement en y passant le mot "start". Et lors de l'arrêt, il exécute séquentiellement tous les "K" (comme "Kill" ) en y passant le paramètre "stop". A toi de faire en sorte que ton script/programme C prenne en compte ces 2 paramètres... |
T'es sûr de ton coup
il me semblait que ça marchait plutôt comme ça : à chaque état du système correspond un runlevel particulier (genre 2 pour le boot normal, 0 pour l'arrêt, etc.). Quand on entre dans un runlevel, le processus init exécute tous les scripts en K avec l'argument stop et les scripts en S avec l'argument start. Mais il me semble qu'on peut avoir des K lors du démarrage et vice-versa.
Marsh Posté le 12-10-2006 à 00:35:48
franceso a écrit : T'es sûr de ton coup |
Euh... c'est pas ce qu'on m'a appris... et j'ai jamais vérifié ta théorie.
Pour moi, les scripts "K" sont lancés quand on quitte un niveau. C'est un truc à voir...
Marsh Posté le 12-10-2006 à 04:17:12
Le système d'init varie beaucoup d'une distrib à l'autre.
Marsh Posté le 12-10-2006 à 12:06:00
Bonjour,
J'ai effectivement utilisé un script dans /etc/init.d pour lancer mon demon. Y a juste un dernier truc qui me chiffone, dans mon script de démarrage, dans la cas de l'argument stop, le code n'est pas exécuté jusqu'au bout, qd je tue mon processus, le script s'acheve (alors que je voulais mettre un petit "Arret du service truc" dans un fichier de log" ). C'est pas très grave mais ce n'est pas l'execution normale donc ca me travaille qd meme .
Edit: j'en profite comme y a un peu de monde pour reposer uen question qui n'a rien à avoir...
Mon gnokii part carrément en vrille: en gros si j'écris un SMS de 160 caractères il mouline comme un âne (il recoit pas de ack du GSM). Bon je me dis c'est soit le cable, soit mon install de Gnokii soit le GSM. Maitnenant si j'écris un message composé uniquement de 160 fois le même caractère (2 a la limite ca passe aussi) le SMS est envoyé...
La limite pour un message composé de caractères différents semble etre autour de 77 caractères.
Bref ca me parait tres tres bizzare...
Marsh Posté le 12-10-2006 à 15:45:33
tieuma a écrit : Y a juste un dernier truc qui me chiffone, dans mon script de démarrage, dans la cas de l'argument stop, le code n'est pas exécuté jusqu'au bout, qd je tue mon processus, le script s'acheve (alors que je voulais mettre un petit "Arret du service truc" dans un fichier de log" ) |
Comment tu fais pour tuer ton processus ? (c'est pas un pkill ou assimilé, quand même ?)
Marsh Posté le 12-10-2006 à 16:18:07
Je me suis inspiré du script présent ici : http://guide.andesi.org/html/kservices.html (section 3)
Marsh Posté le 12-10-2006 à 17:14:33
ok, c'est bien ce qu'il me semblait : le processus est tué grâce à un killall (qui tue sauvagement tous les processus portant le même nom).
Je suppose que tu as donné à ton script de lancement le même nom que ton démon. Du coup, avec le killall, ton script de lancement se suicide en même temps qu'il tue le démon. (enfin, ce n'est qu'une hypothèse, mais il se pourrait bien que ce soit ça).
La méthode killall est un peu brutale. Tu ferais peut-être bien de stocker le pid de ton démon au démarrage (par exemple dans un fichier), et de tuer uniquement ce processus là avec ton script d'arrêt.
Marsh Posté le 12-10-2006 à 17:47:31
franceso a écrit : Tu ferais peut-être bien de stocker le pid de ton démon au démarrage (par exemple dans un fichier), et de tuer uniquement ce processus là avec ton script d'arrêt. |
D'ou l'interet de start-stop-daemon ou l'equivalent sur ta distrib, qui prend soin de tout ca.
Marsh Posté le 12-10-2006 à 17:55:55
Non je me suis inspiré mais j'ai pas fait ca comme un bourrin . Je recupère effectivement le PID de mon processus et je le tue ensuite. D'où mon étonnement de voir mon script mourir
Marsh Posté le 12-10-2006 à 18:10:01
tieuma a écrit : Non je me suis inspiré mais j'ai pas fait ca comme un bourrin . Je recupère effectivement le PID de mon processus et je le tue ensuite. D'où mon étonnement de voir mon script mourir |
tu peux poster ton script ? Comme ça on évitera les suppositions
EDIT: c'est quoi ta distrib ? Comme dit matafan, si tu disposes de start-stop-daemon il vaut mieux l'utiliser.
Marsh Posté le 13-10-2006 à 10:09:38
Code :
|
Je fais un double grep car effectivement j'ai appelé mon script de demarrage du meme nom que mon script "demon". La distrib c'est une Suse 10.0, start-stop-daemon est installé, j'avais essayé de l'utiliser mais un truc ne m'avait pas plu
Marsh Posté le 13-10-2006 à 15:24:20
tieuma a écrit :
|
Bon, déjà "echo `date`" se remplace avantageusement par "date". Il en va de même pour toute autre commande mise en sous-exécution de la commande "echo"...
Ensuite, je connais pas "killall" mais si l'argument "-9" a la même signification que pour kill, pourquoi utiliser le signal 9 (fait pour les cas extrèmes) ?
killall -15 devrait être plus propre puisque le signal "15" demande au processus de se terminer => le processus finit ce qu'il faisait, ferme les fichiers, finalise les écritures en attente et se termine...
tieuma a écrit : La distrib c'est une Suse 10.0, start-stop-daemon est installé, j'avais essayé de l'utiliser mais un truc ne m'avait pas plu |
Oui, la Suse est assez économique car elle ne s'use que quand on s'en sert
Marsh Posté le 13-10-2006 à 16:16:25
ReplyMarsh Posté le 13-10-2006 à 16:34:47
Sve@r a écrit : Bon, déjà "echo `date`" se remplace avantageusement par "date". Il en va de même pour toute autre commande mise en sous-exécution de la commande "echo"... |
Pas con pour le "echo"
Sinon le killall est pas nécessaire de ttes manieres, j'ai qu'un gnokii lancé à la fois. Et même qd j'en ai pas, mon script se fait dégager qd meme.
Sinon pour la Suse, j'ai pas choisi . J'aurai pas pris ca mais je suis pas assez savant en linux pour bien voir la différence avec d'autres distrib (enfin je sais qd même que je préfere apt au gestionnaire de package de Suse ).
@ francesco: oui j'avais vérifié en lançant la commande "à la mano"
Code :
|
le PID de mon service est < à celui du script de démarrage, la mort de mon procsessus "service" semble entrainer la mort de mon script...
Marsh Posté le 13-10-2006 à 16:54:29
tieuma a écrit : le PID de mon service est < à celui du script de démarrage |
C'est ça qui m'étonne le plus... En même temps, c'est peut-être du à la méthode de fonctionnement de startpar (que je ne connaissais pas)
As-tu vérifié avec un pstree (ou autre truc du genre) s'il y a filiation entre ton service et ton script de démarrage (et si oui, dans quel sens) ?
Marsh Posté le 13-10-2006 à 17:22:08
franceso a écrit : C'est ça qui m'étonne le plus... En même temps, c'est peut-être du à la méthode de fonctionnement de startpar (que je ne connaissais pas) |
Voila le pstree:
|-sh---sleep
|-smbd---2*[smbd]
|-sshd-+-2*[sshd---bash]
| `-sshd---bash---pstree
|-startpar
|-syslog-ng
`-udevd
-sh--sleep c'est mon service
Donc pas de lien a priori.
Marsh Posté le 13-10-2006 à 20:34:27
OK, dans ce cas je vois vraiment pas ce qui pourrait tuer ton script d'init lorsque le démon meurt. Désolé...
Marsh Posté le 16-10-2006 à 15:41:35
Pas très grave, ce qui m'embête plus c'est mon appli GSM pas foutue d'envoyer des SMS de 160 caractères
(forum.hardware.fr/hardwarefr/O [...] 0018-1.htm)
Marsh Posté le 05-10-2006 à 10:51:19
Bonjour,
Jai écrit un petit script Shell qui envoie des SMS à partir de fichiers placés dans un répertoire. Le script regarde de temps en temps le dossier et traite les fichiers sil y en a. Comme ce script doit tourner en permanence, je souhaitais le lancer en tant que démon.
Après recherches, je nai pas trouvé comment faire cela, je ne suis même pas sur que cela soit possible. Les scripts de démarrage placés dans « /etc/init.d » ne semblent fonctionner que pour lancer des applications non binaires.
1) Est-ce possible de créer un démon à partir dun script Shell ?
Javais également pensé utiliser « cron » pour lancer périodiquement mon script, le problème est que lenvoi de SMS (par gnokii) peut prendre du temps et donc il faut que je regarde si mon script est déjà en cours dexécution. Bref il faut que « cron » appelle un script qui surveille celui qui envoie les SMS et qui lappelle sil nest pas actif. Je naime pas trop cette solution et en plus je ne sais pas comment tester si mon script denvoi est actif (j'ai que "bash" ou "sh" comme nom dans la liste des processus, donc je ne vois pas trop comment être sur de tester le bon; je pourrai tester l'existence du processus « gnokii » mais il se peut aussi que le test se fasse pendant le scan du répertoire ou même entre 2 appels de « gnokii »).
2) Cette solution est-elle bonne ? Si oui comment tester lactivité du script denvoi des SMS (nommage du script ?)
Enfin je pensais réécrire le script Shell en C pour pouvoir utilisé la méthode classique de lancement de démons (référencement dans /etc/init.d)
3) Est-ce la meilleure solution ?
4) Je suis à la ramasse et je my prends comme un pied (désolé japprends ) ?
Merci pour vos conseils éclairés.
Edit: à la limite je pourrai ecrire le PID du shell qui execute mon script d'envoi dans un fichier et que mon script appelé par cron lise ce fichier. Un peu crade non ?
Message édité par tieuma le 05-10-2006 à 12:26:25