suivre un fichier journal mais n'afficher que des lignes spécifiques

29

Je suis un fichier journal avec le drapeau -f. Ensuite, je redirige ceci vers grep, pour ne trouver que les lignes qui contiennent "X". Cela fonctionne parfaitement bien. Maintenant, je veux rediriger ceci dans un autre grep, qui supprimera toutes les lignes contenant "Y". Lorsque j'ajoute le deuxième canal, le fichier cesse de se rafraîchir et il semble qu'aucune donnée ne vienne.

C'est la commande qui fonctionne: tail -f my_file.log | grep "X"

C'est la commande qui ne fait pas: tail -f my_file.log | grep "X" | grep -v "Y"

Comment dois-je structurer cela pour que la commande fonctionne?

Ori Horev
la source
1
essayez de faire un tuyau par un tuyau, changez la séquence, faites tail -f file|grep -v "Y". si la sortie est correcte, passez à l'ajout grep "X".
Aizuddin Zali

Réponses:

38

Comme la sortie de grepest mise en mémoire tampon, utilisez l' --line-bufferedoption de greppour activer la mise en mémoire tampon de ligne:

tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'

Si votre grepn'a pas l'option, vous pouvez utiliser stdbufcomme alternative:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
heemayl
la source
1
Je me demande comment stdbufdit libstdbuf.soquels paramètres utiliser.
kasperd
@kasperd: variables d'environnement.
Nate Eldredge
1
@NateEldredge J'ai déjà recherché des variables d'environnement dans la sortie de diff -u <(env) <(stdbuf env)et n'en ai trouvé aucune. Mais maintenant je me rends compte que ce que j'aurais dû tester l'était diff -u <(env) <(stdbuf -oL env).
kasperd
Je suis aussi le même genre de problème. mon cas est, je dois imprimer toutes les lignes contiennent «aaa» et «bbb». La première solution ci-dessus ne fonctionne pas. La deuxième solution fonctionne pour «aaa» existe et «bbb» n'existe pas. les deux existent ne fonctionnent pas. ne donnant aucune sortie. ma commande ressemble à ceci: tail -f test.txt | stdbuf -oL grep 'aaa' | grep 'bbb' elle ne donne aucune sortie. Pourriez-vous m'aider s'il vous plait.
Sun
18

Je trouve normalement plus utile awkpour ce genre de vérifications logiques:

tail -f /path/to/log | awk '/X/ && !/Y/'
#                           ^^^    ^^^^
#                   this I want    but not this

Testé en ayant deux onglets, l'un dans lequel je continue d'écrire seq 20 >> myfileet l'autre ayant par exemple tail -f myfile | awk '/3/ && !/13/'.

fedorqui
la source
15

Une autre approche serait d'utiliser une seule grepinvocation au lieu de deux et ainsi d'éviter le problème de mise en mémoire tampon. Utilisez simplement une expression régulière qui correspond à des lignes composées de 0 ou plusieurs caractères non Y, puis d'un X puis de 0 ou de plusieurs non Y jusqu'à la fin de la ligne "

tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'
terdon
la source