2016-10-04 2 views
2

Je dois pouvoir rediriger la sortie vers un fichier et aussi vérifier le code de retour d'un script dans KSH (je ne peux pas utiliser pipestatus ou pipefail), j'ai trouvé une solution mais je ne suis pas sûr Quelle est la signification du fichier Discriptor 4, quelqu'un peut-il expliquer s'il vous plaît?redirection de descripteur de fichier de sortie

{ 
rc=$(
{ 
    { 
    . somescript.sh 2>&1 
    echo "$?" >&3 
    } | tee -a somefile.txt 
} 3>&1 >&4 4>&- 
) 
} 4>&1 

echo "${rc}" 

Répondre

2

rc=$(...) signifie que le code de retour sera tout ce qui est imprimé sur le descripteur de fichier (fd) 1 par le code dans le (...). Donc, en quelque sorte, ce somescript.sh sorties doit être retiré fd 1, puis ramené plus tard. La ligne echo renvoie le code retour somescript.sh à fd 3. Ensuite, 3>&1 envoie le code de retour enregistré à fd 1, où $(...) l'attend. Cependant, cela signifie que le vieux fd 1 (de {somescript 2>&1 } | tee) n'a nulle part où aller. Donc l'ancien fd 1 est redirigé vers fd 4 avec >&4 (et le côté d'entrée est fermé avec 4>&- car il ne sera pas utilisé). Ensuite, une fois que le $(...) est terminé, le 4>&1 à la fin met la sortie du somescript|tee sur fd 1 où d'autres programmes s'attendent à ce qu'il soit.

Ouf!

Sans >&4, la sortie de somescript.sh et la sortie de echo "$?" seraient mélangés sur fd 1 en raison de la 3>&1. Donc fd 4 est un stylo d'attente pour la sortie réelle de somescript.sh pendant le temps que fd 1 est utilisé pour transporter le code de retour.

+0

J'ai toujours pensé que $ (...) se lisait à partir de stdout, ce que fd 1 pointe généralement aussi, mais si cela se lit à partir de fd 1, cela aurait beaucoup de sens. Merci. – dood

+0

fd 1 ne "pointe" pas sur la sortie standard; il * est * sortie standard. – chepner

+0

@chepner ah ok, merci pour la clarification, et normalement stdout points au terminal alors. – dood

1

Si vous êtes prêt à utiliser un tube nommé, vous pouvez vous passer tout le fichier descripteur tiraillements:

mkfifo p 
tee -a somefile.txt < p & 
. somescript.sh > p 
rc=$? 

Ici, nous courons tee en arrière-plan, laissant lire son entrée à partir d'un tube nommé p. Une fois ce travail démarré, nous sourceons le script et redirigeons sa sortie vers le tube nommé. Une fois le script terminé, vous pouvez enregistrer son statut de sortie à rc en utilisant une instruction d'affectation ordinaire. Cela fermera également l'extrémité des coques du tube, ce qui provoquera la fermeture de l'autre extrémité et permettra à tee de sortir.

+0

Si vous avez exécuté ceci avec fd '1' pointant initialement vers le terminal, est-ce que' tee' ... & 'provoquerait' t'' s'arrêter avec un 'SIGTTOU' quand' somescript.sh' a commencé à produire une sortie sur 'p'? – cxw

+0

En théorie, oui, mais 'ksh' devrait remplacer l'action par défaut sur' SIGTTOU' pour permettre à 'tee' d'écrire directement sur le terminal. (Pour être honnête, je devais chercher ce que 'SIGTTOU' était parce que je n'avais pas remarqué de problème quand j'ai testé ça.) – chepner

+0

[" Attention aux bugs dans le code ci-dessus, je l'ai seulement prouvé, je ne l'ai pas essayé . "] (http://staff.science.uva.nl/~peter/knuthnote.pdf) * Knuth * :) Merci! – cxw