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).