2009-01-07 11 views
11

En ce moment je suis en utilisant exec pour rediriger stderr dans un journal d'erreur avecAppend texte à stderr réoriente dans bash

exec 2>> ${errorLog} 

Le seul inconvénient est que je dois commencer chaque série avec un horodatage depuis exec pousse juste le texte directement dans le fichier journal. Est-il possible de rediriger stderr mais permettez-moi de lui ajouter du texte, comme un horodatage?

Répondre

16

Ceci est très intéressant. J'ai demandé à un gars qui sait très bien bash, et il m'a dit de cette façon:

foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; }; 

D'abord, qui crée une fonction de lecture d'une ligne d'entrée brute à partir de stdin, alors que l'affectation à l'IFS rend doesn » t ignore les blancs. Ayant lu une ligne, il la sort avec les données appropriées ajoutées au préalable. Ensuite, vous devez dire bash pour rediriger stderr dans cette fonction:

exec 2> >(foo) 

Tout ce que vous écrivez dans stderr sera maintenant par la fonction foo. Notez quand vous le faites dans un shell interactif, vous ne verrez plus l'invite, car il est imprimé à stderr, et la lecture dans foo est tamponnée par ligne :)

+0

$ foo() {alors que IFS = '' read -r line; fais echo "$ (date) $ line" >> fichier.txt; terminé; } $ exec 2>> (foo) Avertissement: Le programme '/ bin/bash' s'est écrasé. whoops – Peter

+0

Mais si je change ça en: echo 2 | tee> (foo), alors ça marche bien. – Peter

+0

Dans la question, chaque ligne est ajoutée à un fichier déjà ouvert. Dans la réponse, le fichier journal est ouvert pour chaque ligne. Et une recherche à la fin du fichier est également nécessaire. Il peut être préférable de faire un second 'exec' dans' foo'. – ceving

1

Vous pouvez simplement utiliser simplement:

exec 1> >(sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1 

Cela résoudra pas complètement votre problème concernant Prompt non représentés (itt se fera après un peu de temps, mais pas en temps réel, puisque le pipe mettra en cache certaines données ...), mais affichera la sortie 1: 1 sur stdout ainsi que dans le fichier.

Le seul problème est que je ne pouvais pas résoudre, est, de le faire à partir d'une fonction, car cela ouvre un sous-shell, où l'exécutif est inutile pour le programme principal ...

+0

Par ce toutes les lignes obtiennent le même horodatage? – ceving

-1
cat q23123 2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file 
0

Cette L'exemple redirige stdout et stderr sans perdre les fichiers stdout et stderr d'origine. Des erreurs dans le gestionnaire stdout sont également enregistrées dans le gestionnaire stderr. Les descripteurs de fichier sont enregistrés dans des variables et fermés dans les processus enfants. Bash prend soin, qu'aucune collision ne se produise.

#! /bin/bash 

stamp() 
{ 
    local LINE 
    while IFS='' read -r LINE; do 
    echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE" 
    done 
} 

exec {STDOUT}>&1 
exec {STDERR}>&2 
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp) 
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp) 

for n in $(seq 3); do 
    echo loop $n >&$STDOUT 
    echo o$n 
    echo e$n >&2 
done 

Cela nécessite une version Bash actuelle mais grâce à Shellshock on peut compter sur ce aujourd'hui.