Piping tail -f dans awk

J'essaie de pipe tail -f dans awk pour surveiller un fichier journal en temps réel, mais selon les exemples, il ne devrait pas y avoir de problème, mais je ne peux pas le faire fonctionner.

Voici la commande que je cours

tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}' 

Mais quand je modifie mon fichier en utilisant nano, j'ajoute une ligne, il n'est pas imprimé en temps réel. Si je lance la commande awk directement, ma nouvelle ligne apparaît dans le résultat.

Vous ne le voyez pas en temps réel parce que, pour des raisons d'efficacité, les tuyaux sont mis en mémoire tampon. tail -f doit remplir le tampon, généralement 4 kB, avant que la sortie ne passe à awk .

Un correctif consiste à utiliser la commande unbuffer qui fait partie du package attendu:

 unbuffer tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}' 

Ces astuces se transforment en pensant qu'il écrit sur un terminal interactif. En conséquence, il ne bloque pas.

Pour en savoir plus, consultez https://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe

Sinon, si vous possédez GNU coreutils 7.5 ou mieux, vous pouvez désactiver la mise en mémoire tampon de sortie avec la commande stdbuf:

 stdbuf -o0 tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}' 

Je pense que la réponse de @ John1024 n'est pas tout à fait correcte, car le préfixe stdbuf -o0 est mal placé. Il appartient en tant que préfixe à la commande awk , et non à la commande tail -f , donc la commande correcte doit être:

 tail -f logfile.log | stdbuf -o0 awk -F" " '{print $1, $2, $7, $8}' 

Notez également que toutes les versions d'awk ne fonctionneront pas dans cette configuration particulière. IOW, si vous avez besoin de cette chaîne de commande particulière pour fonctionner comme écrite, continuez d'essayer diverses versions awk / gawk / mawk jusqu'à ce que vous frappiez celle qui fonctionne.

Vous pouvez le désactiver en ajoutant une boucle while comme indiqué dans l'exemple ci-dessous. J'ai testé ceci sur un fichier journal en cours d'exécution et cela a fonctionné pour moi.

 tail -f input.log | while read a; do echo "$a" | awk -F" " '{print $1, $2, $7, $8}' >> output.log; done