2009-12-05 5 views
0

J'ai quelques serveurs et autres démons dont j'ai besoin pour démarrer dans la bonne séquence.Comment séquencer des scripts init.d sous Ubuntu

J'ai créé les scripts d'initialisation à partir du squelette de script, et puis les installer pour commencer dans l'ordre approprié à l'aide du système de nommage numéroté, mais quelques questions demeurent:

Un serveur (« serverA ») doit initialiser une connexion de base de données, puis écouter sur un socket. Un autre serveur ('serverB') doit alors se connecter à ce socket, et la connexion échouera si le processus précédent n'est pas encore en écoute. Est-il possible d'empêcher le script init.d pour serverA de se terminer jusqu'à ce que serverA ait commencé à écouter? L'initialisation serverB ne démarre pas tant que l'initialisation serverA n'est pas terminée.

À l'heure actuelle, l'installation fonctionne en demandant à serverB de réessayer la connexion jusqu'à ce qu'elle réussisse, mais cette approche semble fragile. Je voudrais une compréhension plus déterministe de la façon de forcer le séquençage.

Répondre

3

Oui, c'est ma question que je réponds, mais j'ai trouvé cette technique utile, et je partage pour quelqu'un d'autre aux prises avec les mêmes problèmes.

J'ai trouvé que socat était très utile dans l'attente d'un socket ou d'un port. Un script init.d comme:

case “$1″ in 
    start) 
    echo '--benign phrase' | socat - UNIX-CONNECT:/path/to/socket,retry=10,intervall=1 
;; 

attendra jusqu'à ce que le socket devienne accessible en écriture, puis retournera. Il n'y a pas de démonisation impliquée, donc il bloque l'exécution des scripts init.d les plus élevés jusqu'à ce qu'il se termine.

L'utilisation de tels scripts de serveur ralentira la séquence de démarrage, et n'est donc pas optimale, mais constitue une grande amélioration par rapport à l'approche très fragile consistant à saupoudrer les instructions 'sleep n' dans les scripts.

2

Je ne pense pas que ce soit fragile - au moins, je peux penser à un scénario où il ne sera pas fragile. Avoir un temps de réessai de 5 secondes et c'est pas mal du tout. C'est une approche KISS et il n'y a pas de cas d'angle que vous ne comprenez pas.

Obtenir un environnement distribué synchronisé n'est pas pour les faibles de cœur, et c'est exagéré dans votre exemple. Pour vous donner une certaine confiance dans votre approche, je peux vous dire que j'ai des douzaines de processus de serveur complexes écrits à la main et distribués sur une ferme Web, ils ne m'ont jamais donné de chagrin même lorsque les serveurs de bases de données ont disparu. Les troncs de réseau ont baissé etc. Ils continuent simplement à fonctionner en mode dégradé jusqu'à ce que les bases de données reviennent.

2

Si le serveur écoute sur un socket de domaine, vous pouvez créer une boucle qui interroge le socket. Il pourrait y avoir un moyen plus facile de le faire en bash, mais il pourrait ressembler à:

for i in 1 2 3 4 5; do 
    if [ -e '/var/run/myserver.sock' ]; then 
    break 
    fi 
done 

Une autre solution est d'avoir votre serveur ne daemonize jusqu'à ce qu'il ait ouvert la prise d'écoute. De cette façon, le script init s'arrêtera jusqu'à ce que le processus se démonise, ce qui garantit que le socket est disponible.

Bien sûr, cela dépend de l'application de la démonisation par votre application, plutôt que par d'autres moyens. ("/ Usr/bin/myserver &" ou similaires.)

Mise à jour:

Notez également que, ce que vous faites est maintenant tout init type System-V. Ubuntu utilise en fait Upstart, qui est un système basé sur des événements plutôt qu'une séquence de scripts. Vous pouvez choisir d'utiliser des tâches de démarrage plutôt que des scripts d'initialisation System-V et de déclencher un événement Upstart personnalisé à partir de votre serveur, ce qui déclenchera le lancement de votre deuxième serveur. Le Getting Started guide a un exemple de ceci tout en bas. Je ne sais pas s'il existe un moyen d'API, mais il pourrait s'agir simplement d'un "system ("/bin/initctl emit myevent ");" au bon moment dans votre premier serveur. Quelqu'un d'autre avec plus d'expérience Upstart peut être en mesure d'élaborer mieux/plus loin.

+0

Je crois que le socket 'fichier' est toujours là, donc son existence n'est pas un bon indicateur. L'approche de démonétisation différée est prometteuse. J'utilise maintenant la méthode shell '&' (rapide et facile) mais faire la démonisation en interne est assez pragmatique. – Rdbhost

+0

Vous pouvez supprimer le socket avant de lancer le serveur, il devra donc le recréer. (J'ai également oublié, la boucle a probablement besoin d'un court sommeil aussi.) –

+0

Vous pourriez vouloir un sommeil dans cette boucle d'interrogation. – mc0e

Questions connexes