Comment puis-je atteindre
cmd >> file1 2>&1 1>>file2
C'est-à-dire que stdout et stderr doivent être redirigés vers un fichier (fichier1) et que seul stdout (fichier2) doit être redirigé vers un autre (les deux en mode ajout)?
Comment puis-je atteindre
cmd >> file1 2>&1 1>>file2
C'est-à-dire que stdout et stderr doivent être redirigés vers un fichier (fichier1) et que seul stdout (fichier2) doit être redirigé vers un autre (les deux en mode ajout)?
Réponses:
Le problème est que lorsque vous redirigez votre sortie, elle n’est plus disponible pour la prochaine redirection. Vous pouvez diriger tee
dans un sous-shell pour conserver la sortie pour la deuxième redirection:
( cmd | tee -a file2 ) >> file1 2>&1
ou si vous aimez voir la sortie dans le terminal:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
Pour éviter d'ajouter le stderr du premier tee
à file1
, vous devez rediriger le stderr de votre commande vers un descripteur de fichier (par exemple 3), puis l'ajouter à nouveau à stdout:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(merci @ fra-san)
Avec zsh
:
cmd >& out+err.log > out.log
En mode annexe:
cmd >>& out+err.log >> out.log
Dans zsh
et si l' mult_ios
option n'a pas été désactivée, lorsqu'un descripteur de fichier (ici 1) est redirigé à plusieurs reprises pour écriture, le shell implémente une fonction intégrée tee
permettant de dupliquer la sortie vers toutes les cibles.
cmd >& file1 > file2
Vous pouvez: tag stdout (en utilisant un sed UNBUFFERED, c.-à-d. sed -u ...
), Stderr aussi aller sur stdout (non étiqueté, car il n’a pas suivi ce balisage sed), et ainsi pouvoir différencier le 2 dans le fichier journal résultant.
Ce qui suit: est lent (il peut être sérieusement optimisé, en utilisant par exemple un script Perl au lieu de tout le temps ...; do ...; done, par exemple, ce qui engendrera des sous-shell et des commandes à chaque ligne!), Bizarre (il me semble que j'ai besoin des 2 {} étapes dans un renommer stdout puis dans l'autre ajouter le "raté à travers" stderr), etc. Mais c'est: une " preuve de concept " qui essaiera de garder la sortie commande le plus de stdout & stderr autant que possible:
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
ls unknown
) pour imprimer quelque chose sur stderr? >&2 echo "error"
serait bien. (2) tee
peut ajouter plusieurs fichiers à la fois. (3) Pourquoi pas juste cat
au lieu de grep "^"
? (4) votre script échouera au début de la sortie de stderr _stdout_
. (5) Pourquoi?
ls loop
produira à la fois sur stdout et stderr, mélangé (alternativement), dans un ordre contrôlé, afin que nous puissions vérifier que nous avons conservé cette commande stderr / stdout malgré le marquage de stdout 2): gnu tail, peut-être, mais pas queue régulière (ex, sur aix.). 3): grep "^" affiche également les deux noms de fichiers. 4): cela peut être changé par la variable. 5): l'exemple compliqué fonctionne sur d'anciens oses (ex, old aix) où je l'ai testé (pas de perl disponible).
uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)
Si l'ordre de sortie doit être: stdout then stderr ; il n'y a pas de solution avec la redirection uniquement.
Le stderr doit être stocké dans un fichier temporel
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
La description:
La seule façon de rediriger une sortie (un fd comme stdout ou stderr) vers deux fichiers est de la reproduire. La commande tee
est l'outil approprié pour reproduire le contenu d'un descripteur de fichier. Donc, une idée initiale pour avoir une sortie sur deux fichiers serait d'utiliser:
... | tee file1 file2
Cela reproduit le stdin de tee dans les deux fichiers (1 & 2), en laissant la sortie de tee toujours non utilisée. Mais nous devons ajouter (utiliser -a
) et n’avoir besoin que d’une copie. Cela résout les deux problèmes:
... | tee -a file1 >>file2
Pour fournir tee
stdout (celui à répéter), nous devons utiliser stderr directement en dehors de la commande. Une façon, si l’ordre n’est pas important (l’ordre de la sortie sera (très probablement) conservé tel qu’il sera généré, celui qui sera généré en premier sera stocké en premier). Non plus:
cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
L'option 2 ne fonctionne que dans certains coquillages. L'option 3 utilise un sous-shell supplémentaire (plus lent) mais n'utilise les noms de fichiers qu'une seule fois.
Mais si stdout doit être premier (quelle que soit la sortie de l'ordre générée), nous devons stocker stderr pour l'ajouter au fichier à la fin (première solution postée).
sponge
fait:(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
Dans l'intérêt de la diversité:
Si votre système prend en charge /dev/stderr
, alors
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
marchera. La sortie standard de cmd
est envoyée à la fois à la sortie standard et à la sortie standard du pipeline. L'erreur type des cmd
dérivations tee
et sort du stderr du pipeline.
Alors
cmd
, etcmd
, mélangés.Il suffit ensuite d'envoyer ces flux aux fichiers appropriés.
Comme avec presque toutes les approches comme celle-ci (y compris la réponse de Stéphane ), les
file1
lignes peuvent être en panne.
out+err
etout
dire ici. Noms de fichiers? Des flux à rediriger?