J'essaie d'écrire un script shell qui attendra qu'un fichier apparaisse dans le /tmp
répertoire appelé sleep.txt
et une fois qu'il est trouvé, le programme cessera, sinon je veux que le programme soit en veille (suspendu) jusqu'à ce que le fichier soit localisé . Maintenant, je suppose que j'utiliserai une commande de test. Donc, quelque chose comme
(if [ -f "/tmp/sleep.txt" ];
then stop
else sleep.)
Je suis nouveau dans l'écriture de scripts shell et toute aide est grandement appréciée!
shell-script
files
Mo Gainz
la source
la source
$MAILPATH
.Réponses:
Sous Linux, vous pouvez utiliser le sous-système du noyau inotify pour attendre efficacement l'apparition d'un fichier dans un répertoire:
(en supposant Bash pour la
<()
syntaxe de redirection de sortie)L'avantage de cette approche par rapport à l'interrogation à intervalle de temps fixe comme dans
c'est que le noyau dort plus. Avec une spécification d'événement inotify comme
create,open
l'exécution du script est simplement planifiée lorsqu'un fichier sous/tmp
est créé ou ouvert. Avec l'interrogation d'intervalle de temps fixe, vous perdez des cycles de processeur pour chaque incrément de temps.J'ai inclus l'
open
événement pour m'inscrire égalementtouch /tmp/sleep.txt
lorsque le fichier existe déjà.la source
inotifywait -e create,open --format '%f' --quiet /tmp/sleep.txt --monitor > /dev/null ; # continues once /tmp/sleep.txt is created/opened
?inotifywait
est lui-même une boucle while, et il génère une ligne chaque fois que le fichier est ouvert / créé. Vous avez donc besoin de la boucle while pour rompre lorsqu'elle est modifiée.sleep.txt
à un moment donné. Ainsi, aucune condition de concurrence. La question ne contient aucun élément faisant allusion à un scénario que vous avez en tête.Mettez votre test dans la
while
boucle:la source
sleep
est le nombre de secondes à attendre à chaque itération - vous pouvez changer cela en fonction de vos besoins.Il y a quelques problèmes avec certaines des
inotifywait
approches basées sur les données données jusqu'à présent:sleep.txt
fichier qui a été créé d'abord en tant que nom temporaire, puis renommé ensleep.txt
. Il faut correspondremoved_to
événements en plus decreate
sleep.txt
a été créé. Que faire si unfoo\nsleep.txt\nbar
fichier a été créé par exemple?inotifywait
démarrage et l'installation de la montre? Ensuite ,inotifywait
attendrait toujours pour un fichier qui est déjà là. Vous devez vous assurer que le fichier n'est pas déjà là après l' installation de la montre.inotifywait
cours d'exécution (au moins jusqu'à ce qu'un autre fichier soit créé) une fois le fichier trouvé.Pour y remédier, vous pouvez faire:
Notez que nous attendons la création de
sleep.txt
dans le répertoire courant,.
(vous feriez donc uncd /tmp || exit
avant dans votre exemple). Le répertoire en cours ne change jamais, donc quand ce pipeline revient avec succès, c'est unsleep.txt
dans le répertoire en cours qui a été créé.Bien sûr, vous pouvez remplacer
.
par/tmp
ci-dessus, mais pendant qu'ilinotifywait
est en cours d'exécution, il/tmp
pourrait avoir été renommé plusieurs fois (peu probable/tmp
, mais quelque chose à considérer dans le cas général) ou un nouveau système de fichiers monté dessus, donc lorsque le pipeline revient, il peut ne pas être un/tmp/sleep.txt
qui a été créé mais à la/new-name-for-the-original-tmp/sleep.txt
place. Un nouveau/tmp
répertoire aurait également pu être créé dans l'intervalle et celui-là ne serait pas surveillé, donc unsleep.txt
créé là-bas ne serait pas détecté.la source
La réponse acceptée fonctionne vraiment (merci maxschlepzig) mais laisse la surveillance inotifywait en arrière-plan jusqu'à la fin de votre script. La seule réponse qui correspond exactement vos besoins (c'est-à-dire attendre que sleep.txt apparaisse dans / tmp) semble être celle de Stéphane, si le répertoire à surveiller par inotifywait passe de dot (.) À '/ tmp'.
Cependant, si vous souhaitez utiliser UNIQUEMENT un répertoire temporaire pour placer votre indicateur sleep.txt et pouvez parier que personne d'autre ne mettra aucun fichier dans ce répertoire, il suffit de demander à inotifywait de regarder ce répertoire pour les créations de fichiers:
1ère étape: créez le répertoire que vous allez surveiller:
2ème étape: assurez-vous que le répertoire est vraiment là
3ème étape: attendez que TOUT fichier apparaisse à l'intérieur
$directoryToPutSleepFile
Le fichier que vous mettrez
$directoryToPutSleepFile
peut s'appeler sleep.txt awake.txt, peu importe. Le moment où un fichier est créé dans$directoryToPutSleepFile
votre script continuera après l'inotifywait
instruction.la source
sleep.txt
création entre deux appels inotifywait.sleep.txt
est appelé plusieurs fois jusqu'à ce qu'un fichier appelé soit créé. Essayez par exempletouch /tmp/foo /tmp/sleep.txt
, puis une instance deinotifywait
rapporterafoo
et quittera, et au moment où le prochain inotifywait sera démarré, le sleep.txt sera déjà là depuis longtemps donc inotifywait ne détectera pas sa création.en général, il est assez difficile de faire autre chose que la simple boucle de test / sommeil fiable. Le problème principal est que le test va courir avec la création du fichier - à moins que le test ne soit répété, l'événement create peut être manqué. C'est de loin votre meilleur pari dans la plupart des cas où vous utiliseriez Shell pour commencer:
Si vous trouvez que cela est insuffisant en raison de problèmes de performances, l'utilisation de Shell n'est probablement pas une bonne idée en premier lieu.
la source
Sur la base de la réponse acceptée de maxschlepzig (et d'une idée de la réponse acceptée sur /superuser/270529/monitoring-a-file-until-a-string-is-found ), je propose ce qui suit amélioré ( à mon avis) réponse qui peut également fonctionner avec timeout:
Si le fichier n'est pas créé / ouvert dans le délai imparti, l'état de sortie est 124 (selon la documentation du délai (page de manuel)). Dans le cas où il est créé / ouvert, l'état de sortie est 0 (succès).
Oui, inotifywait s'exécute dans un sous-shell de cette façon et ce sous-shell ne se terminera que lorsque le délai d'expiration se produit ou lorsque le script principal se termine (selon la première éventualité).
la source