Comment puis-je utiliser la magie BASH pour y parvenir?
Je veux seulement voir la sortie de stderr à l'écran,
mais je veux que stdout et stderr soient écrits dans un fichier.
Clarification: je veux que stdout et stderr se retrouvent dans le même fichier. Dans l'ordre où ils se produisent.
Malheureusement, aucune des réponses ci-dessous ne le fait.
bash
shell
io-redirection
Andreas
la source
la source
Réponses:
Même sans redirection, ou avec rien mais
>logfile 2>&1
, vous n'êtes pas assuré de voir la sortie dans l'ordre de génération.Pour commencer, la sortie standard de l'application sera mise en mémoire tampon de ligne (vers tty) ou mise en mémoire tampon (dans un pipeline) mais stderr est sans tampon, de sorte que les relations entre l'ordre de sortie sont rompues en ce qui concerne le lecteur. Les étapes suivantes de tout pipeline que vous pourriez concocter n'obtiendront pas un accès ordonné de manière déterministe aux deux flux (ce sont conceptuellement des choses qui se déroulent en parallèle, et vous êtes toujours soumis à l'ordonnanceur - si au moment où votre lecteur obtient une tranche que l'auteur a déjà écrit sur les deux tuyaux, vous ne pouvez pas dire lequel est arrivé en premier).
"[L] e ordre qu'ils se produisent" n'est vraiment connu de l'application. L'ordre de sortie sur stdout / stderr est un problème bien connu - classique, peut-être -.
la source
Lorsque vous utilisez la construction: les
1>stdout.log 2>&1
deux stderr et stdout redirigés vers le fichier parce que le stdout redirection est mis en place avant la stderr redirection.Si vous inversez l'ordre, vous pouvez rediriger stdout vers un fichier, puis copier stderr vers stdout pour pouvoir le diriger vers
tee
.la source
tee -a
avec le même fichier utilisé1>
pour additionner les deux sorties dans le même fichier. Quelque chose comme:./test 2>&1 1>out+err.log | tee -a out+err.log
wget -O - www.google.de
moi. (comparer avec la solution ci-dessous)tee -a
ne fonctionnera pas de manière fiable pour avoir la même sortie que celle qui serait sur la console si rien n'était redirigé. La sortie qui passetee
peut être légèrement retardée par rapport à la sortie qui vient directement de la commande et peut donc apparaître plus tard dans le journal.J'ai pu accomplir cela en plaçant la ligne suivante en haut d'un script bash:
Cela redirigera stdout vers le fichier
log
(1>>log
), puis tee stderr vers le fichierlog
(2> >(tee -a log
) et le redirigera vers stderr (>&2)
. De cette façon, j'obtiens un seul fichierlog
, qui montre à la fois stdout et stderr dans l'ordre, et stderr est également affiché à l'écran comme d'habitude.Le hic, c'est que cela ne semble fonctionner que lorsque j'ajoute au fichier. Si je n'ajoute pas, il semble que les deux redirections s'entrechoquent, et je n'obtiens que la dernière sortie.
la source
Vous souhaitez dupliquer le flux d'erreurs afin qu'il apparaisse à la fois sur la console et dans le fichier journal. L'outil pour cela est
tee
, et tout ce que vous devez faire est de l'appliquer au flux d'erreurs. Malheureusement, il n'y a pas de construction shell standard pour diriger le flux d'erreurs d'une commande dans une autre commande, donc un petit réarrangement des descripteurs de fichiers est nécessaire.la source
tee
introduit un délai ici aussi. Je ne pense pas qu'il existe une solution pure shell. En fait, je me demande s'il existe une solution sans modifier l'application d'une manière ou d'une autre.Pour écrire stderr sur écran et écrire les deux stderr et stdout dans un fichier - ET faire en sorte que les lignes pour stderr et stdout sortent dans le même ordre que si elles étaient écrites sur l'écran:
Se révèle être un problème difficile, en particulier la partie concernant la "même séquence" à laquelle vous vous attendez si vous les écriviez simplement à l'écran. En termes simples: écrivez chacun dans son propre fichier, faites un peu de magie en arrière-plan pour marquer chaque ligne (dans chaque fichier) avec l'heure exacte à laquelle la ligne a été produite, puis: "tail --follow" le fichier stderr à l'écran , mais pour voir les deux "stderr" et "stdout" ensemble - dans l'ordre - trier les deux fichiers (avec des marquages d'heure exacte sur chaque ligne) ensemble.
Code:
Oui, cela semble élaboré et il en résulte 4 fichiers de sortie (dont 2 que vous pouvez supprimer). Il semble que ce soit un problème difficile à résoudre, il a donc fallu plusieurs mécanismes.
En fin de compte, pour voir les résultats des deux stdout et stderr dans la séquence que vous attendez, exécutez ceci:
La seule raison pour laquelle la séquence est au moins très proche de ce qu'elle aurait été si stdout et stderr étaient simplement passés à l'écran est: chaque ligne est marquée avec un horodatage jusqu'à la milliseconde.
Pour voir stderr à l'écran au cours du processus, utilisez ceci:
J'espère que cela aide quelqu'un qui est arrivé ici longtemps après que la question initiale a été posée.
la source
Soit
f
la commande que vous aimeriez exécuter, alors cecidevrait vous donner ce que vous souhaitez. Par exemple,
wget -O - www.google.de
cela ressemblerait à ceci:la source
Compte tenu de ce que j'ai lu ici, la seule solution que je puisse voir serait d'ajouter à chaque ligne STOUT ou STERR un timelice / timestamp. date +% s arriverait en secondes, mais cela ralentirait pour maintenir l'ordre. De plus, le journal devrait en quelque sorte être trié. Plus de travail que je n'en suis capable.
la source
J'ai eu du mal avec cette exigence exacte, et finalement je n'ai pas trouvé de solution simple. J'ai fini par faire ceci:
Il ajoute stdout et stderr, dans l'ordre entrelacé approprié, au fichier journal. Et si des erreurs se sont produites (comme déterminé par l'état de sortie de la commande), il envoie la sortie entière (stdout et stderr) à stdout, toujours dans un ordre entrelacé approprié. J'ai trouvé que c'était un compromis raisonnable pour mes besoins. Si vous voulez un fichier journal à exécution unique plutôt qu'un fichier multi-exécution croissant, c'est encore plus simple:
la source
stderr à la commande
tee -a
, et stdout s'ajoutant au même fichier:et notez: aussi assurez-vous que l'ordre est correct (mais sans stderr-show), il y a une commande 'unbuffer' des outils 'expect', qui simule tty et maintient stdout / err dans l'ordre comme il le montrerait sur le terminal:
la source