Je veux regarder un fichier jusqu'à ce qu'un peu de texte apparaisse
J'ai trouvé cette réponse :`tail -f` jusqu'à ce que le texte soit vu
mais quand je l'ai essayé sur ubuntu, ça ne se ferme pas :
$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$
fonctionne comme prévu. cependant, lorsque j'essaie de suivre le fichier
$ tail -f test.txt | sed '/w/ q'
one
two
ça ne sort jamais. la queue ne s'arrête pas même si le tuyau est cassé.
Est-ce que quelqu'un sait comment faire tail quitter quand sed sort ?
Réponse acceptée :
C'est la même chose que dans :
- Comment quitter plus tôt à la fermeture du tuyau ?
- Grep tarde à se fermer après avoir trouvé une correspondance ?
- limiter la sortie de recherche ET éviter le signal 13
Dans :
cmd1 | cmd2
Votre shell attend jusqu'à cmd1 se termine même après cmd2 a déjà pris fin. Ce n'est pas le cas de tous les coquillages. Certains comme le shell Bourne ou Korn ne le font pas par exemple.
Lorsque cmd2 meurt, le tuyau sur cmd1 's stdout devient cassé , mais cela ne termine pas cmd1 instantanément.
cmd1 se terminera la prochaine fois qu'il essaiera d'écrire dans ce tube. Il recevra alors un SIGPIPE dont l'action par défaut est de terminer le processus.
Avec cmd1 ==tail -f file et cmd2 ==sed /w/q , tail -f lira les 10 dernières lignes du fichier et les écrira dans stdout (le tube), généralement en un seul morceau, à moins que les lignes ne soient vraiment grosses et reste là en attendant que plus de texte soit ajouté au file .
sed , qui s'exécute simultanément, attendra une entrée sur son stdin, la lira, la traitera ligne par ligne et quittera s'il y a une ligne qui contient w .
Dès (ou éventuellement avec un délai d'une ligne avec quelques sed implémentation) lorsqu'il trouve cette ligne, il quitte, mais à ce moment-là, tail a déjà écrit dans le tube tout ce qu'il avait à écrire, donc il ne recevra pas de SIGPIPE à moins qu'un texte supplémentaire ne soit ajouté plus tard au fichier (à ce moment-là, il fera le fatal write() ).
Si vous vouliez cmd1 pour terminer dès que cmd2 se termine, vous auriez besoin de quelque chose pour le tuer une fois cmd2 se termine. Comme avec :
sh -c 'echo "$$"; exec tail -f test.txt' | {
IFS= read pid
sed /w/q
kill -s PIPE "$pid"
}
Ou avec bash :
{ sed /w/q; kill -s PIPE "$!"; } < <(exec tail -f text.txt)
Modification 2020
Comme l'a noté @ user414777, depuis la version 8.28, l'implémentation GNU de tail , dans les modes de suivi, non seulement interroge désormais les nouvelles données dans le ou les fichiers qu'il surveille, mais vérifie également si sa sortie standard devient un tuyau cassé et se termine immédiatement (ou dans la seconde si inotify n'est pas utilisé), ce qui rend inutiles les solutions ci-dessus.
Notez cependant que seul GNU tail effectue ce type de traitement, pas une autre implémentation de tail (AFAIK), et aucun autre utilitaire (même les implémentations GNU).
Ainsi, alors que :
tail -f file | head -n1
Quittera après une ligne,
tail -f file | tr '[:lower:]' '[:upper:]' | head -n1
par exemple ne sera pas nécessairement comme tr ne surveillera pas si sa sortie standard devient un tuyau cassé, et ne mourra donc que s'il écrit quelque chose après que le tuyau se soit cassé comme d'habitude (et ce n'est qu'à ce moment-là que GNU tail -f sortira).