Comment rediriger stderr et stdout vers différents fichiers et également les afficher dans le terminal?

30

Je veux voir la sortie d'une commande dans le terminal comme s'il n'y avait pas de redirection. De plus, stderr doit être redirigé vers err.log et stdout doit être redirigé vers stdout.log.

Ce serait bien d'avoir également la copie exacte de ce qui est affiché dans le terminal, c'est-à-dire les erreurs imprimées au fur et à mesure que cela se produit, dans un fichier séparé: stdouterr.log.

balki
la source
@Nuno Non ce n'est pas le cas. L'OP veut avoir différents fichiers pour stdout et stderr.
dogbane
@dogbane Oui, vous avez raison. Désolé pour ça.
Nuno C. Inácio,
Je trouve toujours cette question très familière. Permettez-moi de regarder vers le haut ... Voici un très similaire unix.stackexchange.com/q/4195/250 , et voici un unix.stackexchange.com/q/1416/250 connexe
phunehehe

Réponses:

37

Utilisez la teecommande comme suit:

(cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log

3>&1 1>&2 2>&3 est la façon dont vous échangez stderr et stdout, car tee ne peut accepter que stdout.

Jetez un œil à la commande Unix tee pour des redirections plus avancées en utilisant tee.

dogbane
la source
belle solution. Existe-t-il un moyen d'obtenir le code de sortie cmd?
turbanoff
2
@turbanoff Remplacer cmdpar (cmd ; echo >exit_code.txt $?).
Parthian Shot
Je crois que cela devrait mieux préserver l'ordre des choses en sortie sur la ligne de commande:((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log)
TTT
5

Je pense que la connexion de stdout et stderr à deux fichiers différents est une idée magnifique. Ne rend-il pas les journaux asynchrones? J'ai donc essayé ce qui suit:

  • stdout à "stdout.log" (comme l'a suggéré Dogbane)
  • stderror à "stderr.log" (comme l'a suggéré Dogbane)
  • toutes les sorties vers "all.log" et
  • être toujours en mesure de voir la sortie sur l'écran (dans un terminal séparé!)

((cmd | tee stdout.log) 3>&1 1>&2 2>&3 | tee stderr.log) &> all.log

dans un autre terminal

tail -f --sleep-interval=2 all.log
Sreeni
la source
N'est-il pas possible de diriger stderr directement vers un deuxième terminal? Aucun fichier journal n'est alors requis.
Steven Lu
@StevenLu oui, si vous connaissez le nom et que vous avez la permission d'écrire au deuxième terminal, cela peut être fait.
Jasen
1
plus facile serait &| tee all.logà la fin de la commande au lieu de&> all.log
Jasen
@Jasen: 2ème fois que je vois &|. Je comprends &>, |&aussi, mais qu'est-ce que &|signifie dans ce contexte? Je n'ai pas pu trouver une référence de syntaxe appropriée, pas sur le net, même pas en consultant la page de manuel bash "bash (1)" ... Tx
Cbhihe
1
@Cbhihe pour autant que je sache, cela ne fait rien, je voulais dire|&
Jasen
3

@dogbane, merci.
J'ai également trouvé un autre moyen qui enregistre les deux flux à peu près dans l'ordre car ils seraient imprimés sans redirection.

command 2> >(tee errlog | tee -a bothLog > /dev/tty ) | tee outlog | tee -a bothLog

Mais cela ne fonctionne qu'avec les shells qui prennent en charge la substitution de processus.

balki
la source
-2

essaye ça :

command 2>&1 | tee bothLog
vasile
la source
4
Bonjour vasile, cela ne répond pas à la question: balki a besoin de fichiers séparés pour stdout et stderr, votre solution mélangerait les deux dans le même flux.
Mat
Pourquoi les gens fusionnent-ils stdout et stderr ensemble? Ou dites aux autres de le faire?
nurettin