Je sais comment utiliser tee
pour écrire la sortie ( STDOUT
) de aaa.sh
to bbb.out
, tout en l'affichant toujours dans le terminal:
./aaa.sh | tee bbb.out
Comment pourrais-je maintenant également écrire STDERR
dans un fichier nommé ccc.out
, tout en l'ayant affiché?
Réponses:
Je suppose que vous voulez toujours voir STDERR et STDOUT sur le terminal. Vous pouvez opter pour la réponse de Josh Kelley, mais je trouve que garder un
tail
arrière-plan qui génère votre fichier journal est très hackish et maladroit. Remarquez comment vous devez conserver un exra FD et faire le nettoyage par la suite en le tuant et que vous devriez techniquement le faire dans atrap '...' EXIT
.Il y a une meilleure façon de faire, et que vous avez déjà découvert:
tee
.Seulement, au lieu de simplement l'utiliser pour votre stdout, ayez un tee pour stdout et un pour stderr. Comment allez-vous y parvenir? Substitution de processus et redirection de fichiers:
Divisons-le et expliquons:
>(...)
(substitution de processus) crée un FIFO et permet de l'tee
écouter. Ensuite, il utilise>
(redirection de fichiers) pour rediriger le STDOUT decommand
vers le FIFO que votre premiertee
écoute.Même chose pour le second:
Nous utilisons à nouveau la substitution de processus pour créer un
tee
processus qui lit à partir de STDIN et le sauvegarde dansstderr.log
.tee
renvoie son entrée sur STDOUT, mais comme son entrée est notre STDERR, nous voulons redirigertee
le STDOUT de notre STDERR à nouveau. Ensuite, nous utilisons la redirection de fichiers pour redirigercommand
le STDERR de l'entrée FIFO (tee
le STDIN).Voir http://mywiki.wooledge.org/BashGuide/InputAndOutput
La substitution de processus est l'une de ces très belles choses que vous obtenez en prime de choisir
bash
votre shell par opposition àsh
(POSIX ou Bourne).Dans
sh
, vous devez faire les choses manuellement:la source
$ echo "HANG" > >(tee stdout.log) 2> >(tee stderr.log >&2)
qui fonctionne, mais attend l'entrée. Y a-t-il une raison simple à cela?/bin/bash 2> err
et/bin/bash -i 2> err
(echo "Test Out";>&2 echo "Test Err") > >(tee stdout.log) 2> >(tee stderr.log >&2)
pourquoi pas simplement:
Cela redirige simplement
stderr
àstdout
, donc tee échos à la fois au journal et à l' écran. Peut-être que je manque quelque chose, car certaines des autres solutions semblent vraiment compliquées.Remarque: depuis bash version 4, vous pouvez utiliser
|&
comme abréviation pour2>&1 |
:la source
./aaa.sh |& tee aaa.log
fonctionne alors (en bash).set -o pipefail
suivi de;
ou&&
si je ne me trompe pas.Cela peut être utile pour les personnes qui trouvent cela via google. Décommentez simplement l'exemple que vous souhaitez essayer. Bien sûr, n'hésitez pas à renommer les fichiers de sortie.
la source
exec >
signifie, déplacer la cible d'un descripteur de fichier vers une certaine destination. La valeur par défaut est 1, donc,exec > /dev/null
déplace la sortie de stdout vers / dev / null à partir de maintenant dans cette session. Les descripteurs de fichiers actuels pour cette session peuvent être vus en faisantls -l /dev/fd/
. Essayez! Ensuite, voyez ce qui se passe lorsque vous émettezexec 2>/tmp/stderr.log.
En outre,exec 3>&1
signifie, créez un nouveau descripteur de fichier avec le numéro 3 et redirigez-le vers la cible du descripteur de fichier 1. Dans l'exemple, la cible était l'écran lorsque la commande a été émise.Pour rediriger stderr vers un fichier, affichez stdout à l'écran et enregistrez également stdout dans un fichier:
EDIT : Pour afficher à la fois stderr et stdout à l'écran et également enregistrer les deux dans un fichier, vous pouvez utiliser la redirection d'E / S de bash :
la source
En d'autres termes, vous voulez diriger stdout dans un filtre (
tee bbb.out
) et stderr dans un autre filtre (tee ccc.out
). Il n'y a aucun moyen standard de diriger autre chose que stdout dans une autre commande, mais vous pouvez contourner cela en jonglant avec les descripteurs de fichiers.Voir aussi Comment grep flux d'erreur standard (stderr)? et quand utiliseriez-vous un descripteur de fichier supplémentaire?
Dans bash (et ksh et zsh), mais pas dans d'autres shells POSIX tels que dash, vous pouvez utiliser la substitution de processus :
Attention, en bash, cette commande revient dès la
./aaa.sh
fin, même si lestee
commandes sont toujours exécutées (ksh et zsh attendent les sous-processus). Cela peut être un problème si vous faites quelque chose comme./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.out
. Dans ce cas, utilisez plutôt le jonglage de descripteur de fichier ou ksh / zsh.la source
sh
, utile pour les tâches cron, où la substitution de processus n'est pas disponible.Si vous utilisez bash:
Le crédit (ne répondant pas du haut de ma tête) va ici: http://www.cygwin.com/ml/cygwin/2003-06/msg00772.html
la source
Dans mon cas, un script exécutait une commande lors de la redirection de stdout et stderr vers un fichier, quelque chose comme:
Je devais le mettre à jour de telle sorte qu'en cas d'échec, prendre certaines mesures en fonction des messages d'erreur. Je pourrais bien sûr supprimer le dup
2>&1
et capturer le stderr du script, mais les messages d'erreur ne seront pas enregistrés dans le fichier journal pour référence. Alors que la réponse acceptée de @lhunath est censée faire la même chose, elle redirigestdout
etstderr
vers différents fichiers, ce qui n'est pas ce que je veux, mais cela m'a aidé à trouver la solution exacte dont j'ai besoin:Avec ce qui précède, le journal aura une copie des deux
stdout
etstderr
et je peux capturerstderr
de mon script sans avoir à se soucierstdout
.la source
Les éléments suivants fonctionneront pour KornShell (ksh) où la substitution de processus n'est pas disponible,
La vraie astuce ici, est la séquence de
2>&1 1>&3
laquelle, dans notre cas, redirige lestderr
versstdout
et redirige lestdout
descripteur vers3
. À ce stade, lestderr
etstdout
ne sont pas encore combinés.En effet, le
stderr
(asstdin
) est passé à l'tee
endroit où il se connectestderr.log
et redirige également vers le descripteur 3.Et le descripteur l'
3
enregistrecombined.log
tout le temps. Ainsi, lecombined.log
contient à la foisstdout
etstderr
.la source
Si vous utilisez zsh , vous pouvez utiliser plusieurs redirections, vous n'avez donc même pas besoin
tee
:Ici, vous redirigez simplement chaque flux vers lui - même et le fichier cible.
Exemple complet
Notez que cela nécessite la
MULTIOS
définition de l' option (qui est la valeur par défaut).la source