Envoyer la sortie bash -x au fichier journal sans interrompre la sortie standard

12

Existe-t-il un moyen d'envoyer les informations affichées en exécutant un script bash avec l'option -x dans un fichier, sans modifier la sortie standard vue par un utilisateur exécutant le script?

Il s'agit d'une fonctionnalité de débogage que j'aimerais implémenter dans un script bash que nous utilisons et qui change fréquemment.

Très appréciée.

désolé docteur de rose
la source

Réponses:

21

La sortie de -x va vers stderr, pas stdout. Mais même cela peut être un problème - de nombreux scripts auront des dépendances fonctionnelles sur le contenu de stderr, et son genre de désordre d'avoir le débogage et les flux stderr mélangés dans certains cas.

Les versions Bash> 4.1 offrent une solution différente: la variable d'environnement BASH_XTRACEFD vous permet de spécifier un descripteur de fichier qui sera utilisé pour envoyer le flux de débogage à. Cela peut être un fichier ou un tuyau ou toute autre bonté unix-y que vous aimez.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Avec un peu plus de violon, vous pouvez faire d'autres choses - comme faire un `` tee '' sur les flux stdout et / ou stdin, et entrelacer ceux avec la sortie de débogage, afin que votre journal soit plus complet. Pour plus de détails à ce sujet, voir /programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Le gros avantage de cette approche par rapport aux alternatives est que vous ne risquez pas de modifier le comportement de votre script en injectant une sortie de débogage dans stdout ou stderr.

Stabledog
la source
Voir également ici comment trouver un descripteur de fichier inutilisé pour le fichier.
jarno
Est-il nécessaire de fermer le descripteur de fichier (c'est-à-dire la ligne exec 19>&-)? D'après mon expérience, il est fermé automatiquement lorsque le script se termine.
jarno
1
Le code ci-dessus ne suppose pas que vous exécutez un script, ni combien de temps le script peut être, etc. être fermé juste parce que le shell entier disparaît à la fin du script. Donc, dans ce cas d'utilisation, vous n'avez pas strictement besoin de fermer la poignée. Mais en général, lors du codage par rapport à une ressource, c'est une bonne pratique de fermer ce que vous avez ouvert, car alors votre code peut être utilisé dans un contexte plus large où le ménage est plus susceptible d'avoir de l'importance.
Stabledog
Pourquoi exportez-vous BASH_XTRACEFD? Pourquoi ne pas simplement en définir la valeur?
jarno
Quoi qu'il en soit, une autre façon de fermer le descripteur de fichier consiste à définir une nouvelle valeur (par exemple, null) pour BASH_XTRACEFD ou à la désactiver.
jarno
4

set -xn'envoie rien à la sortie standard, il n'y a donc aucun problème. Ce qu'il fait , c'est écrire sur l'erreur standard, qui va à la console par défaut.

Ce que vous voulez faire, c'est rediriger stdout vers un autre fichier, comme ceci:

/bin/sh -x /my/script/file 2>/my/log/file
womble
la source
1

Tu vois man tee.

Vous l'exécutez comme tee commandname filenameet il affichera la sortie des commandes stdoutet l'écrira également filename.

Sven
la source