Comment redirect stdout et stderr vers un file et afficher stderr sur console?

Je sais comment redirect vers un file, et utiliser tee; sur un niveau de base. Alors

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"' # A fake "application" displaying both output and error messages. $ outanderr 1>file # redirect stdout to a file, display stderr stderr $ outanderr 2>file # redirect stderr to a file, display stdout stdout $ outanderr 1>file 2>&1 # redirect both to a file, display nothing $ outanderr | tee file; echo "-- file contents --" && cat file # redirect stdout to a file, display both (note: order is messed up) stderr stdout -- file contents -- stdout $ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file # redirect both to a file, display both stdout stderr -- file contents -- stdout stderr 

La question est: quoi écrire à la place des points d'interrogation pour get le résultat ci-dessous:

 $ outanderr ???; echo "-- file contents --" && cat file # redirect both to a file, display stderr stderr -- file contents -- stdout stderr 

Constaint:

  • En supposant que bash.
  • La command doit être conservée dans le file.
  • Les contenus stderr sont affichés en time réel ligne par ligne, c'est-à-dire sans mise en memory tampon.
  • Des files de script séparés peuvent être utilisés.
  • La magie peut être nécessaire.

 2>&1 >>outputfile | tee --append outputfile 

Pour des tests faciles:

 echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile | tee --append outputfile; echo "outputfile:"; cat outputfile 

Modifier 1:

Cela fonctionne en écrivant stdout (uniquement) dans le file, en créant sterr stdout pour qu'il passe par le tube, et que tee écrive sa sortie dans le même file.

Les deux écritures doivent être faites en mode d'ajout ( >> au lieu de > ) sinon les deux écraseraient les autres sorties.

Comme le tuyau est un tampon, il n'y a aucune garantie que la sortie apparaisse dans le file dans le bon ordre. Cela ne changerait même pas si une application était connectée aux deux descripteurs de files (deux canaux). Pour un ordre garanti, les deux sorties doivent passer par le même canal et être marquées respectivement. Ou vous auriez besoin de quelques trucs vraiment fantaisistes:

  1. Si stdout et stderr étaient redirigés vers un file (pas le même file!) Et que les deux files se trouvaient sur un volume FUSE, le module FUSE pourrait marquer chaque écriture avec un horodatage afin qu'une seconde application puisse sortinger datatables correctement et les combiner pour le file de sortie réel. Ou vous ne marquez pas datatables, mais le module crée le file de sortie combiné. Probablement il n'y a pas encore de module FUSE qui fait ça …
  2. Stdout et stderr peuvent être dirigés vers /dev/null . Les sorties de l'application seraient séparées en l'exécutant via strace -f -s 32000 -e trace=write . Vous devriez inverser l'échappement dans ce cas. Inutile de dire que l'application ne court pas plus vite en étant tracée.
  3. Peut-être que la même chose pourrait être atteinte en utilisant un module FUSE simple existant et en traçant le module à la place de l'application. Cela peut être plus rapide que le suivi de l'application car (ou plutôt: si) le module a probablement beaucoup less de syscalls que l'application.
  4. Si l'application elle-même peut être modifiée: L'application pourrait être arrêtée après chaque sortie (mais je pense que cela est possible de l'intérieur seulement) et continuer seulement après avoir reçu le signal s (SIGUSR1 ou SIGCONT). La lecture de l'application à partir du tuyau devrait vérifier à la fois le tuyau et le file pour de nouveldatatables et pour envoyer le signal après chaque nouvelle donnée. Selon le type d'application, cela peut être plus rapide ou même plus lent que la méthode strace. FUSE serait la solution de vitesse maximale.