J'ai essayé de trouver une réponse à cette question, mais je n'ai pas eu de chance jusqu'à présent:
J'ai un script qui exécute d'autres scripts, et bon nombre de ces autres scripts contiennent "set -x", ce qui les oblige à imprimer chaque commande qu'ils exécutent. Je voudrais m'en débarrasser mais conserver les informations si l'un des scripts envoie le message d'erreur à stderr.
Je ne peux donc pas simplement écrire ./script 2>/dev/null
De plus, je n'ai pas les privilèges pour modifier ces autres scripts, donc je ne peux pas modifier manuellement l'option définie.
Je pensais à tout enregistrer de stderr au fichier séparé et filtrer les commandes de traçage, mais peut-être y a-t-il un moyen plus simple?
./script 2>some_file
Réponses:
Avec
bash
4.1 et supérieur, vous pouvez faire(fonctionne également lorsque
bash
est invoqué en tant quesh
).Fondamentalement, nous disons
bash
de sortir laxtrace
sortie sur le descripteur de fichier 7 au lieu de la valeur par défaut de 2, et de rediriger ce descripteur de fichier vers/dev/null
. Le nombre fd est arbitraire. Utilisez un fd supérieur à 2 qui n'est pas utilisé autrement dans votre script. Si le shell dans lequel vous entrez cette commande estbash
ouyash
, vous pouvez même utiliser un nombre supérieur à 9 (bien que vous puissiez rencontrer des problèmes si le descripteur de fichier est utilisé en interne par le shell).Si le shell à partir duquel vous appelez ce
bash
script estzsh
, vous pouvez également faire:pour que la variable soit automatiquement affectée au premier fd libre supérieur à 9.
Pour les anciennes versions de
bash
, une autre option, si lextrace
est activé avecset -x
(par opposition à#! /bin/bash -x
ouset -o xtrace
) serait de redéfinirset
comme une fonction exportée qui ne fait rien une fois passée-x
(bien que cela briserait le script s'il (ou tout autrebash
script qu'il invoque) utiliséset
pour définir les paramètres de position).Comme:
Une autre option consiste à ajouter une interruption DEBUG dans un
$BASH_ENV
fichier qui le faitset +x
avant chaque commande.Cela ne fonctionnera pas quand
set -x
c'est fait dans un sous-shell.Comme l'a dit @ilkkachu, à condition d'avoir la permission d'écrire sur n'importe quel dossier du système de fichiers, vous devriez au moins être en mesure de faire une copie du script et de le modifier.
S'il n'y a nulle part où vous pouvez écrire une copie du script, ou s'il n'est pas pratique de créer et de modifier une nouvelle copie chaque fois qu'il y a une mise à jour du script original, vous pouvez toujours faire:
Cela (et l'approche de copie) peut ne pas fonctionner correctement si le script fait quelque chose d'extraordinaire avec
$0
ou des variables spéciales comme$BASH_SOURCE
(comme la recherche de fichiers qui sont relatifs à l'emplacement du script lui-même), vous devrez donc peut-être faire plus d'édition comme remplacer$0
par le chemin du script ...la source
{BASH_XTRACEFD}>
astuce fonctionne également dansbash
4.1 ou version ultérieure.ksh93
oubash
en ce que la variable ne passe pas dans l'environnement de la commande (comparer<shell> -c 'export fd; printenv fd {fd}> /dev/null'
àzsh
,bash
etksh93
). Vous pouvez le faire fonctionner enksh93
/bash
en le faisant en deux étapes ou éventuellement en utilisanteval
, mais pourbash
, cela aurait des effets secondaires si l'option xtrace était activée.Puisqu'il s'agit de scripts, vous pouvez en faire des copies et les modifier.
En dehors de cela, le filtrage de la sortie semble simple, vous pouvez explicitement définir
PS4
quelque chose de plus inhabituel qu'un simple plus, pour rendre le filtrage plus facile:(bien sûr, cela réduira stdout et stdin, mais la tuyauterie juste stderr dans Bash devient un peu poilue, donc je l'ignorerai)
la source
PS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
.bash
a des problèmes car ilgrep
est exécuté de manière asynchrone (bash ne l'attend pas, donc il peut (et le fait souvent) sortir des choses après le démarrage de la prochaine commande dans le script).