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)?
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.
out+err
etout
dire ici. Noms de fichiers? Des flux à rediriger?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:
la source
ls unknown
) pour imprimer quelque chose sur stderr?>&2 echo "error"
serait bien. (2)tee
peut ajouter plusieurs fichiers à la fois. (3) Pourquoi pas justecat
au lieu degrep "^"
? (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
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: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: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).
la source
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
, alorsmarchera. La sortie standard de
cmd
est envoyée à la fois à la sortie standard et à la sortie standard du pipeline. L'erreur type descmd
dérivationstee
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.la source