Je saute juste sous Unix dans un monde différent et je voulais savoir si
while true
do
/someperlscript.pl
done
Le script perl lui-même possède en interne un observateur de dossier / fichier qui s'exécute lorsque les fichiers sont modifiés à l'emplacement cible.
Est-ce ( while true
) une bonne idée? Sinon, quelle est la meilleure approche privilégiée?
TIA
EDIT: Étant donné que cela semble avoir généré un peu d'intérêt, voici le scénario complet. Le script perl lui-même surveille un répertoire à l'aide d'un observateur de fichiers. À la réception de nouveaux fichiers (ils arrivent via rsync), il récupère le nouveau et le traite. Maintenant, les fichiers entrants peuvent être corrompus (ne demandez pas .. provenant d'un Raspberry Pi), et parfois le processus peut ne pas être en mesure de le gérer. Je ne sais pas exactement pourquoi, car nous ne connaissons pas encore tous les scénarios.
MAIS - si le processus échoue pour une raison quelconque, nous voulons qu'il soit opérationnel et traite le fichier suivant, car le fichier suivant est complètement indépendant du précédent qui pourrait avoir causé l'erreur.
Habituellement, j'aurais utilisé une sorte de fourre-tout et enveloppé tout le code autour de lui pour qu'il ne se bloque JAMAIS. Mais n'était pas sûr pour Perl.
D'après ce que j'ai compris, utiliser quelque chose comme supervord est une bonne approche pour cela.
inotify
API afin d'éviter une boucle occupée attendant que les fichiers changent dans votre répertoire cible.Réponses:
Cela dépend de la vitesse à laquelle le script perl revient. S'il revient rapidement, vous voudrez peut-être insérer une petite pause entre les exécutions pour éviter la charge du processeur, par exemple:
Cela empêchera également un porc CPU si le script n'est pas trouvé ou se bloque immédiatement.
La boucle pourrait également être mieux implémentée dans le script perl lui-même pour éviter ces problèmes.
Éditer:
Comme vous avez écrit la boucle, le seul but est de redémarrer le script perl en cas de panne, une meilleure approche serait de l'implémenter en tant que service surveillé, mais la façon précise de le faire dépend du système d'exploitation. Par exemple: Solaris smf, Linux systemd ou un redémarrage basé sur cron.
la source
while sleep 1; do ...
pour enregistrer le véritable appel.until ! sleep 1; do ...; done
enregistrera toujours cet appel intégré tout en démarrant le script immédiatement.sleep 1& /someperlscript.pl; wait
.until
instruction, je l'ai confondue avec unedo/until
boucle hypothétique qui n'existe pas dans le shell.Les autres réponses, concernant l'utilisation
inotify
, sont correctes, mais ne répondent pas à cette question.Un superviseur de processus, tel que
supervisord
,upstart
ourunit
, est conçu pour exactement le problème de surveillance et de redémarrage d'un service en cas de panne.Votre distribution est probablement livrée avec un superviseur de processus intégré.
la source
while true
est bien comme une construction polyvalente "boucle pour toujours". Comme le disent d'autres réponses, le corps de la boucle ne doit pas être vide, ou devenir vide en raison de la commande à l'intérieur de la boucle qui ne fonctionne pas.Si vous utilisez Linux, vous voudrez peut-être utiliser une commande comme
inotifywait
, ce qui rend lawhile
boucle beaucoup plus simple:Ici, la
inotifywait
commande va s'asseoir et attendre qu'un événement de système de fichiers se produise (dans cet exemple, lorsque les fichiers du répertoire sont écrits). À ce stade, il se termine avec succès et le corps de la boucle s'exécute. Il recommence ensuite à attendre. Parce que lainotifywait
commande attend que quelque chose se produise dans le répertoire, elle est beaucoup plus efficace que d'interroger continuellement le répertoire.la source
Déplacez le while 1 dans le script perl (suite à la suggestion de @roaima)
la source
Lorsque votre script perl est destiné à continuer à fonctionner tout le temps, pourquoi utiliser la construction while? Lorsque Perl échoue en raison d'un problème grave, le nouveau script Perl démarré par while peut se bloquer tout aussi durement. Encore et encore et ainsi de suite.
si vous voulez vraiment recommencer votre perl, pensez à crontab et à un script qui vérifie d'abord les instances en cours d'exécution. De cette façon, votre script sera même lancé après un redémarrage.
la source
En général, il n'y a aucun problème d'utilisation
while true
car il s'agit d'un petit test qui n'est exécuté qu'après la fin du script perl. Gardez à l'esprit qu'en fonction de la variante Linux / Unix que vous utilisez, le script peut se terminer à la déconnexion. Dans ce cas, envisagez d'utiliser la boucle dans un script et appelez-la avecnohup
et mettez-la en arrière-plan, c'est-à-direnohup myscript &
Si le script perl se termine trop souvent et provoque une charge CPU, cette charge est imputable au script perl et non au
while true
.Voir aussi
man nohup
pour plus de détails.la source
Si vous souhaitez gérer un processus, vous pouvez envisager un gestionnaire de processus pour le faire.
Avec de nombreux systèmes récents, vous pouvez utiliser systemd pour surveiller vos processus (ce qui est l'un des avantages de systemd par rapport aux scripts init classiques). Si votre distribution de choix n'utilise pas systemd, vous pouvez utiliser daemontools ou monit .
la source
mon
est une alternative simple, si l'énormité accablante de monit et systemd vous dérange autant qu'ils me font.La
while
boucle n'est vraiment pas une bonne idée. Il n'y a pas d'échappatoire là-bas - cela fonctionne pour toujours - statiquement . Un certain nombre de choses pourraient changer dans l'environnement et cela ne sera pas affecté - et cela pourrait être mauvais.Par exemple, si l'exécutable du shell responsable de cette
while
boucle est mis à niveau, le noyau ne pourra pas libérer l'espace disque pour l'ancienne version tant que ce script ne se fermera pas car il doit maintenir le descripteur tant qu'il s'exécute. Et cela est vrai pour tous les fichiers que le shell peut avoir ouverts pour une raison quelconque pour exécuter la boucle - ils seront tous maintenus ouverts par cettewhile
boucle aussi longtemps qu'elle s'exécutera - pour toujours.Et si, Dieu nous en préserve, il y a une fuite de mémoire n'importe où dans le shell exécutant cette boucle - même le plus petit - elle continuera simplement à fuir - statiquement . Il sera construit sans contrôle et le seul recours est de le tuer de force, puis de le recommencer juste pour faire la même chose plus tard.
Ce n'est vraiment pas la façon dont vous devez configurer un processus en arrière-plan - du moins, pas à mon avis. Au lieu de cela, comme je pense, il devrait y avoir un point de réinitialisation - une actualisation du script et de son état. La façon la plus simple de le faire est d'utiliser
exec
. Vous pouvez remplacer le processus actuel par un nouveau - tout en conservant le même PID - tout en exécutant un nouveau processus.Par exemple, si votre
perl
script doit renvoyer true après avoir correctement géré une modification de fichier dans un répertoire surveillé:...ou quelque chose comme ça. Quelque chose qui permet aux machines de base derrière la boucle de se rafraîchir de temps en temps.
la source
J'ai voté pour certaines de ces réponses, mais j'ai instinctivement les sentiments les plus chaleureux pour la réponse de @ WalterA. Eh bien, je l'ai fait jusqu'à ce que je crée ma propre réponse ...
Personnellement, j'aurais tendance à mettre à jour le script Perl pour qu'il écrive une entrée de journal descriptive sur l'échec et envoie une alerte à un administrateur.
Si le script Perl doit continuer à s'exécuter, en attendant les événements de modification du système de fichiers, pourquoi échoue-t-il?
Si ce n'est pas le cas, pourquoi vous souciez-vous de l'envelopper dans un script pour le redémarrer à l'infini?
S'il y a un problème de configuration ou une dépendance cassée qui provoque l'abandon du script Perl, il est peu probable que le redémarrer à plusieurs reprises le fasse soudainement fonctionner.
Vous connaissez la définition de la folie, non? (faire la même chose encore et encore, en attendant un résultat différent). Je dis juste. ;-)
la source