bash: définir les journaux -x dans un fichier

18

J'ai un script shell avec set -xune sortie verbeuse / déboguée:

#!/bin/bash

set -x
command1
command2
...

La sortie ressemble à ceci:

+ command1
whatever output from command1
+ command2
whatever output from command2

Mon problème est, la sortie de la coquille (causée par set -x) va au stderr, mélangé à la sortie des commandes ( command1, command2...). Je serais heureux d'avoir la sortie "normale" à l'écran (comme le script sans exécuter set -x) et la sortie "extra" de bash séparément dans un fichier.

J'aimerais donc avoir ceci à l'écran:

whatever output from command1
whatever output from command2

et ceci dans un fichier journal:

+ command1
+ command2

(aussi bien si le fichier journal contient tout)

Le set -x 2> fileprendre de toute évidence doens't l'effet escompté, car ce n'est pas la sortie de la commande set, mais changer le comportement du bash.

L'utilisation bash 2> filede l'intégralité du script ne fait pas non plus la bonne chose, car elle redirige également le stderr de chaque commande qui s'exécute dans ce shell, donc je ne vois pas le message d'erreur des commandes.

redseven
la source
2
Mon google-fu semble être fort ce matin: envoyer la sortie bash -x au fichier journal sans interrompre la sortie standard
steeldriver

Réponses:

20

Sur la base de cette réponse ServerFault Envoyer la sortie bash -x vers le fichier journal sans interrompre la sortie standard , les versions modernes de bash incluent BASH_XTRACEFDspécifiquement pour spécifier un autre descripteur de fichier pour la sortie deset -x

Ainsi, par exemple, vous pouvez faire

#!/bin/bash

exec 19>logfile
BASH_XTRACEFD=19

set -x
command1
command2
...

pour envoyer la sortie de set -xdans un fichier logfiletout en préservant la sortie standard régulière et les flux d'erreurs standard pour les commandes suivantes.

Notez que l'utilisation de fd 19 est arbitraire - il suffit juste d'être un descripteur disponible (c'est-à-dire pas 0, 1, 2 ou un autre nombre que vous avez déjà alloué).

tournevis
la source
Il enregistre en effet le journal de trace bash séparément, mais il est vraiment difficile de lire les 2 sorties (stdout + stderr à l'écran et la trace bash dans les fichiers journaux) car elles sont complètement désynchronisées. Voir la solution que je viens de poster .
redseven
4

Après plus d'un an, j'ai trouvé la bonne solution pour avoir à la fois la sortie "normale" (stdout + stderr - bash trace) à l'écran et tous ensemble (stdout + stderr + bash trace) dans un fichier (bash.log) :

exec   > >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)
exec 19> bash.log

export BASH_XTRACEFD="19"
set -x

command1
command2
redseven
la source
C'est juste la combinaison de la réponse de Steeldriver et de celle-ci .
jarno
3

Steeldriver vous a donné une approche. Alternativement, vous pouvez simplement rediriger STDERR vers un fichier:

script.sh 2> logfile

Cela signifie cependant que la sortie créée par l' set -xoption et tout autre message d'erreur produit iront dans le fichier. La solution de Steeldriver ne redirigera que la set -xsortie, ce qui est probablement ce que vous voulez.

terdon
la source
"... la sortie créée par l'option set -x et tout autre message d'erreur produit iront dans le fichier." Et c'est pourquoi cela ne fonctionne pas pour moi. Mon principal problème est que je ne vois pas facilement de "vraies erreurs", car toute cette sortie bash va au stderr. Rediriger les messages d'erreur des commandes me cacherait également les «vraies erreurs» d'une manière différente.
redseven
@redseven J'ai bien peur que ce que vous demandez ne soit pas très clair. Pourriez-vous modifier votre question et clarifier? Essayez d'éviter d'utiliser le terme «sortie» pour tout ce qui ne va pas à Stdout. Voulez-vous séparer i) la sortie normale; ii) des erreurs générées par votre commande et iii) set -x? La réponse de Steeldriver n'est-elle pas suffisante alors? Sinon, montrez-nous un script simple que nous pouvons copier et dites-nous comment vous souhaitez qu'il se comporte.
terdon
@steeldriver a déjà parfaitement répondu à la question.
redseven
@redseven ah, cool alors. Étant donné que votre commentaire est venu tellement plus tard, je pensais que vous aviez encore besoin de quelque chose et je ne voyais pas comment la réponse de Steeldriver n'avait pas résolu votre problème. Heureux que tout soit trié alors.
terdon