2012-03-22 3 views
4

Combien de fois avez-vous vu quelqu'un essayer de "Enregistrer la commande que je cours et la sortie de la commande"? Cela arrive souvent, et pour voir la commande que vous exécutez set -v est agréable, (set -x est sympa, aussi, mais il peut être plus difficile à lire), mais que se passe-t-il lorsque vous voulez capturer la commande en cours d'exécution ... mais pas toutes les commandes en cours d'exécution?bash: capture de la sortie de set -v

Exécution interactive Je ne vois pas un moyen de capturer la sortie set -v du tout.

set -v 
echo a 1>/dev/null # 'echo a 1>/dev/null' is printed to the screen 
echo a 2>/dev/null # 'echo a 2>/dev/null\na' is printed to the screen 

Je peux mettre dans un script et les choses s'améliorer:

echo 'set -v'$'\n''echo a' > setvtest.sh 

bash setvtest.sh 1>/dev/null # 'echo a' is printed to the screen 
bash setvtest.sh 2>/dev/null # 'a' is printed to the screen 

Aha, donc d'un script, il va à stderr. Qu'en est-il en ligne?

set +v 
{ set -v ; echo a ; } 1>/dev/null # no output 
set +v 
(set -v ; echo a ;) 1>/dev/null # no output 

Hmm, pas de chance là-bas.

Fait intéressant, et comme une note de côté, ce ne produit aucune sortie:

echo 'set -v ; echo a' > setvtest.sh 
bash setvtest.sh 1>/dev/null 

Je ne sais pas pourquoi, mais peut-être est aussi la raison pour laquelle la version ne retourne rien sous-shell.

Qu'en est-il des fonctions shell?

setvtest2() { 
    set -v 
    echo a 
} 

setvtest2    # 'a' 
set +v 
setvtest2 1>/dev/null # nothing 
set +v 
setvtest2 2>/dev/null # nothing 

Maintenant la question: Y at-il un bon moyen de capturer la sortie de set -v?

Voici mon pas pirater-nice, donc je suis à la recherche de quelque chose de moins fou:

#!/usr/bin/env bash 

script=/tmp/$$.script 
output=/tmp/$$.out 

echo 'set -v'$'\n'"$1" >"$script" 

bash "$script" 1>"$output" 
cat "$output" 
rm -f "$script" "$output" 

Maintenant, je peux exécuter des scripts simples

bash gen.sh 'echo a' 1>/dev/null # prints 'echo a' 
bash gen.sh 'echo a' 2>/dev/null # prints 'a' 

Mais sûrement il y a de meilleures façons.

Répondre

4

Vous pouvez exécuter bash avec option -v au lieu de tourner sur et en dehors par set:

bash -v -c "echo a" 1>/dev/null # prints 'echo a' 
bash -v -c "echo a" 2>/dev/null # prints 'a' 

Le côté sombre de cette solution est que chacune de ces lignes, il faudra à créer un nouveau processus bash, mais vous ne devrez pas oublier de désactiver l'option v, car elle est activée uniquement dans un processus enfant.

+0

Maintenant * que * est beaucoup moins hacky. Ma solution de contournement a engendré une tonne de processus bash de toute façon, donc c'est une amélioration directe. – Sorpigal

+0

Étant donné que personne ne semble avoir une meilleure idée, j'accepte celui-ci. – Sorpigal

1

que diriez-vous

#!/bin/bash 
set -o xtrace 
Stuff..... 
+0

Hors de portée! Je n'essaie pas de résoudre le problème d'origine, j'essaie de capturer la sortie de 'set -v'. – Sorpigal

+1

Peut-être pouvez-vous appeler bash avec l'option -o, elle ne fait que passer à l'interpréteur. comme bash -o xtrace gen.sh, alors vous pouvez capturer la sortie dans stderr. Je pense que set -v est le même que set -o verbose, donc bash -o verbose gen.sh devrait faire le travail. – pizza