1 votes

tail-pipe-awk script, bien sur Centos mais bizarre sur Ubuntu

J'ai écrit un script sur CentOS et maintenant j'essaie de l'exécuter sur Ubuntu et il se comporte de manière inattendue. Voici quelque chose comme le script, que j'exécute sous bash :

sudo tail -F /var/opt/my-application/log/my-application.log |
awk '
BEGIN {
    ORS=" "
}
{ if ($8 ~ /MATCH-TEXT/) {
            # do a whole bunch of stuff here
            # like look in /proc and calculate CPU and interface stats
    };
 };
} '

Auparavant, lorsqu'une ligne avec MATCH-TEXT apparaissait dans le champ $8 de mon journal, tout le "faire un tas de trucs" (la viande du script) se produisait et je voyais la sortie. Mon application génère des lignes MATCH-TEXT environ une fois par seconde (parfois plus, parfois moins) et il en va de même pour la sortie de ce script.

Maintenant, cependant, lorsque je lance ce script, je n'obtiens aucune sortie pendant un long moment, puis j'obtiens peut-être 30 lignes de sortie d'un coup. Il semble que le script mette en file d'attente les lignes de journal qu'il reçoit, puis s'exécute plusieurs fois rapidement parce que les calculs sur le CPU et l'interface sont justes pour "depuis une minuscule fraction de seconde" plutôt que "depuis une seconde".

Plus étrange encore, le fait de commenter toute la viande de la commande awk pour la remplacer par un "print $0" (transformant l'ensemble du script en une commande grep maladroite) produit le même résultat. Je suis donc convaincu que c'est la façon dont le système exécute ce script et non quelque chose dans le script lui-même.

Pendant ce temps, dans une autre fenêtre, un simple "sudo tail -F mon-application.log | grep MATCH-TEXT" est affiché toutes les secondes environ (comme prévu).

Une idée de ce qui se passe ici ? Des indications sur la façon dont je devrais commencer à chercher la cause de ce comportement de mise en file d'attente ?

1voto

Tabakhase Points 131

Si cela n'est pas dû à une différence dans tail alors je suis d'accord avec Hauke Laging pour dire qu'il s'agit probablement d'un problème de mise en mémoire tampon. Pour vider le tampon de sortie de awk essayez d'ajouter fflush() après vos instructions d'impression comme je l'ai fait dans le code de test suivant :

tail -F /var/log/apache2/access_log | awk '{ if ($8 ~ /MATCH-TEXT/) { print $0; fflush(); }}'

1voto

jg3 Points 169

Après avoir cherché toutes les réponses et essayé fflush et stdbuf (que je ne connaissais pas auparavant, merci), j'ai trouvé que la réponse est en deux parties :

1) CentOS utilise gawk, Ubuntu utilise mawk (par défaut).

Je n'ai aucun commentaire à faire sur ce qui est le mieux ou pourquoi la décision d'utiliser l'un ou l'autre. a été prise, ce sont les différences qui rendent les deux distributions différentes. ( :

2) mawk a une option de ligne de commande pour "interactive", d'après la page de manuel :

 -W interactive

 sets unbuffered writes to stdout and line buffered reads from stdin.
 Records from stdin are lines regardless of the value of RS.

Je ne peux que supposer que c'est parce que la mise en mémoire tampon était dans awk et non dans le script lui-même qui fait que cela fonctionne là où stdbuf ne fonctionne pas.

0voto

Maddin Points 11

Mawk -W interactif a corrigé mon problème sur Debian Wheezy.

    tail -f data.log | grep --line-buffered '$DataString' | mawk -W interactive -F "," '{print "var2", $2, "var4", $4}'

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X