web-dev-qa-db-fra.com

Comment rediriger la sortie vers un fichier et stdout

Dans bash, appeler foo afficherait toute sortie de cette commande sur la sortie standard.

L'appel de foo > output redirigerait toute sortie de cette commande vers le fichier spécifié (dans ce cas, 'sortie').

Existe-t-il un moyen de rediriger la sortie vers un fichier et l'affiche sur stdout?

754
SCdF

La commande que vous voulez s'appelle tee:

foo | tee output.file

Par exemple, si vous ne vous souciez que de stdout:

ls -a | tee output.file

Si vous voulez inclure stderr, faites:

program [arguments...] 2>&1 | tee outfile

2>&1 redirige le canal 2 (erreur standard/stderr) vers le canal 1 (sortie standard/standard), de sorte que les deux soient écrits en tant que sortie standard Il est également dirigé vers le fichier de sortie donné à partir de la commande tee.

De plus, si vous voulez ajouter dans le fichier journal, utilisez tee -a comme:

program [arguments...] 2>&1 | tee -a outfile
1031
Zoredache
$ program [arguments...] 2>&1 | tee outfile

2>&1 vide les flux stderr et stdout .tee outfile prend le flux qu'il reçoit et l'écrit sur l'écran et dans le fichier "outfile".

C'est probablement ce que la plupart des gens recherchent. La situation probable est que certains programmes ou scripts travaillent dur depuis longtemps et produisent beaucoup de résultats. L'utilisateur veut vérifier périodiquement s'il y a progrès, mais veut aussi que la sortie soit écrite dans un fichier.

Le problème (en particulier lors du mélange de flux stdout et stderr) est qu’il faut compter sur les flux vidés par le programme. Si, par exemple, toutes les écritures sur stdout sont non vidées, mais que toutes les écritures sur stderr sont vidées, elles se retrouveront alors hors de l'ordre chronologique dans le fichier de sortie et à l'écran.

Il est également mauvais si le programme ne génère qu'une ou deux lignes toutes les quelques minutes pour signaler les progrès. Dans un tel cas, si la sortie n'était pas purgée par le programme, l'utilisateur ne verrait même aucune sortie à l'écran pendant des heures, car rien de cela ne serait poussé dans le tuyau pendant des heures.

Mise à jour: Le programme unbuffer, qui fait partie du package expect, résoudra le problème de mise en mémoire tampon. Cela provoquera l'écriture immédiate de stdout et stderr sur l'écran et le fichier et de les synchroniser lors de la combinaison et de la redirection vers tee. Par exemple.:

$ unbuffer program [arguments...] 2>&1 | tee outfile
459
Matthew Alpert

Vous pouvez principalement utiliser Zoredachesolution , mais si vous ne voulez pas écraser le fichier de sortie, vous devez écrire avec les options -a en:

ls -lR / | tee -a output.file
16
O.Badr

Quelque chose à ajouter ...

Le paquet unbuffer a des problèmes de support avec certains paquets sous Fedora et les versions unix redhat.

Mettre de côté les ennuis 

Suivre a travaillé pour moi

bash myscript.sh 2>&1 | tee output.log

Merci ScDF & matthew vos contributions m'ont fait gagner beaucoup de temps ..

11
nitinr708

utiliser tail -f output devrait fonctionner.

6
Chuck Phillips

Réponse en prime depuis que ce cas d'utilisation m'a amené ici:

Dans le cas où vous devez le faire comme un autre utilisateur  

echo "some output" | Sudo -u some_user tee /some/path/some_file

Notez que l'écho se produira comme vous et que l'écriture du fichier se produira comme "un_utilisateur" ce quePASfonctionnera si vous exécutez l'écho comme "un_utilisateur" et redirigez la sortie avec >> "un_fichier" parce que la redirection de fichier se fera comme vous.

Astuce: tee prend également en charge l'ajout de l'indicateur -a. Si vous devez remplacer une ligne d'un fichier par un autre utilisateur, vous pouvez exécuter sed en tant qu'utilisateur souhaité.

3
jorfus

< command > |& tee filename # Ceci créera un fichier "nom de fichier" avec le statut de la commande comme contenu. Si un fichier existe déjà, il supprimera le contenu existant et écrira le statut de la commande.

< command > | tee >> filename # ceci ajoutera le statut au fichier mais n'imprimera pas le statut de la commande sur standard_output (screen).

Je veux imprimer quelque chose en utilisant "echo" à l'écran et ajouter les données en écho à un fichier

echo "hi there, Have to print this on screen and append to a file" 
0
kiran sai

Vous pouvez le faire pour tout votre script en utilisant quelque chose comme ça au début de votre script:

#!/usr/bin/env bash

test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee mylogfile ; exit $? ; }

# do whaetever you want

Ceci redirige les sorties stderr et stdout vers le fichier mylogfile et laisse tout aller sur stdout en même temps .

Il est utilisé des astuces stupides:

  • utilisez exec sans commande pour configurer les redirections,
  • utilisez tee pour dupliquer les sorties,
  • redémarrez le script avec les redirections recherchées,
  • utilisez un premier paramètre spécial (un simple caractère NUL spécifié par la notation $'string' spéciale bash) pour indiquer que le script est redémarré (aucun paramètre équivalent ne peut être utilisé par votre travail d'origine),
  • essayez de conserver le statut de sortie d'origine lors du redémarrage du script à l'aide de l'option pipefail.

Moche mais utile pour moi dans certaines situations.

0
Bruno BEAUFILS