Le té n'obtient pas la sortie entière du tuyau

12

J'ai un script exécutant des commandes comme:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH;./some_app -i $INDEX | tee $LOG
echo "Number of errors: $(grep "ERROR" $LOG | wc -l)"

Le problème est probablement dans le tuyau tee. Il ne semble pas obtenir la sortie entière. Lorsque l'application se ferme, les dernières lignes de la sortie (généralement celles contenant une erreur fatale) sont manquantes. Lorsque j'exécute l'application sans pipe pour les teeobtenir dans la sortie.

Comment puis-je forcer le script à attendre que le tee termine le traitement de toutes les sorties?

Ladislav Mrnka
la source
Cela fonctionne-t-il bien si vous le connectez à un fichier, pas à stdout?
Pilot6

Réponses:

23

L'erreur fatale sort probablement dans STDERR (2), pas STDOUT (1). Vous pouvez rediriger STDERR vers STDOUT avec 2>&1et le tube devrait également le capturer.

./some_app -i $INDEX 2>&1 | tee $LOG

Si vous avez des problèmes de mise en mémoire tampon, vous pouvez le forcer à un état sans tampon:

stdbuf -o0 ./some_app -i $INDEX 2>&1 | tee $LOG
Oli
la source
Bon, on se rapproche. Maintenant, je vois que l'erreur fatale est en cours d'impression, mais encore une fois, elle n'est pas terminée. La ligne avec l'erreur se termine juste au milieu et la sortie d'écho continue. Il y a encore un problème avec le vidage du tampon ou simplement en attente de la fin de cette partie.
Ladislav Mrnka
Édité. Assez rare dans mon expérience que quelque chose glisse si complètement à travers les tampons à la sortie, mais ça vaut le coup.
Oli
1
Terminé! Je vous remercie. Je pose peut-être trop de questions, mais quelqu'un comprend-il pourquoi je dois désactiver la mise en mémoire tampon lorsque je passe à un autre processus?
Ladislav Mrnka
@Oli Un très bon!
Pilot6
6

Comme les messages d'erreur sont normalement affichés sur STDERR (descripteur de fichier 2), vous devez rediriger STDOUT et STDERR vers tee:

./some_app -i "$INDEX" |& tee "$LOG"

Lorsque vous le faites, ./some_app -i $INDEX | tee $LOGvous redirigez uniquement le STDOUT vers tee.

|& entraînera la redirection de STDOUT et de STDERR.

Si vous ne pouvez pas rediriger uniquement le STDOUT (comme vous l'étiez):

./some_app -i "$INDEX" | tee "$LOG"

En revanche si vous souhaitez rediriger uniquement le STDERR:

./some_app -i "$INDEX" 2>&1 >/dev/null | tee "$LOG"
heemayl
la source