J'ai un script qui mesure la durée d'exécution d'une commande.
Il a besoin de la "vraie" time
commande, ce qui signifie, un binaire par exemple dans /usr/bin/time
(car le bash-built-in n'a pas le -f
drapeau).
Ci-dessous, un script simplifié qui peut être débogué:
#!/bin/bash
TIMESEC=$(echo blah | ( /usr/bin/time -f %e grep blah >/dev/null ) 2>&1 | awk -F. '{print $1}')
echo ABC--$TIMESEC--DEF
if [ "$TIMESEC" -eq 0 ] ; then
echo "we are here!"
fi
Enregistrez sous "test.sh" et exécutez:
$ bash test.sh
ABC--0--DEF
we are here!
Donc ça a marché.
Maintenant, essayons de déboguer ceci en ajoutant "-x" à la ligne de commande bash:
$ bash -x test.sh
++ echo blah
++ awk -F. '{print $1}'
+ TIMESEC='++ /usr/bin/time -f %e grep blah
0'
+ echo ABC--++ /usr/bin/time -f %e grep blah 0--DEF
ABC--++ /usr/bin/time -f %e grep blah 0--DEF
+ '[' '++ /usr/bin/time -f %e grep blah
0' -eq 0 ']'
test.sh: line 10: [: ++ /usr/bin/time -f %e grep blah
0: integer expression expected
Pourquoi ce script se casse-t-il lorsque nous utilisons "-x" et fonctionne correctement sans lui?
bash
shell-script
Tomasz Chmielewski
la source
la source
-x
on, la$()
construction obtient la-x
sortie incluse dans le cadre de sa valeur résultante. Je ne sais pas si c'est un comportement "attendu" ou un bogue ... Ou peut-être que c'est le sous-shell à l'()
intérieur qui donne la-x
sortie.BASH_XTRACEFD
vous permet de rediriger laset -x
sortie vers un endroit où cela pose moins de problèmes.Réponses:
Le problème est cette ligne:
où vous redirigez l'erreur standard pour qu'elle corresponde à la sortie standard. bash écrit ses messages de trace dans l'erreur standard, et utilise (par exemple) son intégré
echo
avec d'autres constructions de shell dans le processus bash.Si vous le changez en quelque chose comme
il contournera ce problème et sera peut-être un compromis acceptable entre le traçage et le travail:
la source
vous pouvez également simplement déposer le sous-shell. ce sont apparemment les coquilles imbriquées qui finissent par se bouleverser:
Si tu fais:
... vous vous retrouvez avec le sous-shell lancé pour gérer cette section du pipeline hébergeant le sous-shell à l'intérieur. Parce que le shell sans redirige même la sortie de débogage du sous-shell à l'intérieur (comme il le ferait également pour tout autre type de
{
commande composée que; } >redirect
vous pourriez choisir d'utiliser) vers sa section du pipeline, vous finissez par mélanger les flux. Cela a à voir avec l'ordre de redirection.Au lieu de cela, si vous redirigez tout d'abord uniquement la sortie d'erreur des commandes que vous essayez d'évaluer, et laissez la sortie du shell hôte arriver à stderr, vous ne vous retrouvez pas avec le même problème.
et donc...
... le shell hôte est libre de continuer à écrire son stderr où il veut tout en ne redirigeant que la sortie des commandes qu'il appelle dans le pipe.
D'ailleurs...
la source