2010-08-23 6 views
4

J'ai trouvé que la commande tcl exec renvoie la chaîne de stdout d'abord, puis stderr. Par exemple, mon "script de test" suivant génère des messages dans cet ordre:tcl exec lit d'abord stdout puis stderr?

puts "test started" 
puts stderr "some non-fatal error goes to stderr" 
puts "test passed" 

Puis-je exécuter le script comme ceci:

set ret [ catch { exec sh -c $cmd } msg ] 

et ce que je reçois de $ msg est:

test started 
test passed 
some non-fatal error goes to stderr 

et cela me rend vraiment difficile d'obtenir le bon résultat.

Quelqu'un peut-il laisser se savoir s'il est possible d'obtenir les messages à la fois stdout et stderr dans l'ordre, et:

1) s'il vous plaît ne pas rediriger comme celui-ci, ce qui peut les obtenir tous pour effet:

set ret [ catch {exec $cmd >&log.txt} msg ] 

2) Je dois appeler que script Tcl dans mon script tcl, désolé

3) Je ne peux pas la source du script de test .tcl directement becau Il ya d'autres scripts appelés entre les deux et il ne fonctionnera pas si mon script tcl source juste ce script tcl.

J'utilise tclsh 8.3

Je ne sais pas si cela demande trop. J'espère que quelqu'un peut comprendre cela. Merci.

+1

Voir http://wiki.tcl.tk/stderr pour plus de conseils. –

Répondre

5

Tout d'abord, nous allons définir une commande simple pour les besoins des tests que nous pouvons être sûr, essai juste ce dont nous avons besoin:

set cmd "echo a; echo b >&2; echo c" 

Ensuite, nous utilisons un petit aide supplémentaire pour gérer la fusion des flux stdout et stderr (division de la commande sur plusieurs lignes pour plus de clarté afin que nous puissions voir où l'wrapperest et où l'exec est enveloppé):

set ret [catch { 
    exec sh -c $cmd |& cat 
} msg] 

Si nous testons, nous trouverons que nous obtenons $ret être 0, et $msg étant le commandé correctement:

a 
b 
c 

COMMEnT ça marche? L'astuce est |&, qui effectue la fusion lors de l'acheminement vers un autre processus. (Nous utilisons cat parce qu'il passe juste choses à travers sans interférer.)

Si vous utilisez Tcl 8.6 (en version bêta), vous pouvez utiliser chan pipe pour produire un canal que vous pouvez rediriger stdout et stderr dans le 2>@ fileId form, mais ce n'est pas si utile pour toi. (Vous êtes conscient que 8.3 est plutôt obsolète? Même 8.4 n'est plus vraiment supporté, 8.5 est ce que le code de production est recommandé de cibler.

+0

Vous auriez plus d'options si vous avez fait un pipeline avec 'open', mais c'est plus complexe à assembler. –

+0

génial !! cool!! Bien que pas très clair du mécanisme, je suis si heureux de voir votre message et d'utiliser ce code. Je vous remercie! –

+0

Le mécanisme est "' & & 'envoie à la fois stdout et stderr au processus suivant dans le pipeline". J'utilise 'cat' pour juste le passer à travers. –

-1

Utilisez la commande source au lieu de exec que vous souhaitez appeler un script Tcl à partir d'un autre script Tcl:

set ret [catch {source $cmd} msg] 
+0

Merci ardsrk. Mais désolé l'appel est comme ceci: mon appel de script tcl -> un fichier shell .sh qui définit les variables système et appels -> le script de test tcl. Si je me contente de créer le script .tcl, cela ne fonctionnera pas. –

+0

J'ai modifié ma question pour faire une déclaration claire. J'aurais dû. –

Questions connexes