web-dev-qa-db-fra.com

suivre un fichier journal mais ne montrer que des lignes spécifiques

Je termine un fichier journal avec l'option -f. Ensuite, je passe ceci à grep, pour ne trouver que les lignes contenant "X". Cela fonctionne parfaitement bien. Maintenant, je veux diriger ceci à nouveau dans un autre grep, qui supprimera toutes les lignes contenant "Y". Lorsque j'ajoute le deuxième canal, le fichier cesse de se régénérer 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 le fait pas: tail -f my_file.log | grep "X" | grep -v "Y"

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

25
Ori Horev

Comme la sortie de grepest mise en mémoire tampon, utilisez l'option --line-buffered de greppour activer la mise en mémoire tampon des lignes:

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

Si votre grepne dispose pas de cette option, vous pouvez utiliser stdbufcomme alternative:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
33
heemayl

Je trouve normalement plus utile awk pour ce type de vérification logique:

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 >> myfile et l'autre ayant par exemple tail -f myfile | awk '/3/ && !/13/'.

17
fedorqui

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

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