Écriture des sorties vers le fichier log et la console

dans L'interpréteur de commandes Unix, j'ai un fichier env ( le fichier env définit les paramètres requis pour exécuter le script utilisateur comme le nom et le chemin du fichier log, rediriger les sorties et les erreurs vers le fichier log, les détails de connexion à la base de données, etc ) qui redirige toutes les sorties ( messages d'écho ) et les erreurs vers le fichier log à partir du script exécuté en utilisant le code suivant:

exec 1>>${LOG_FILE}
exec 2>>${LOG_FILE}

le fichier env est exécuté au début de chaque script. En raison du code ci-dessus dans le fichier env, toutes les sorties de la console qui peuvent être des sorties de l'utilisateur ou des erreurs sont directement sorties dans le fichier log qui est ce dont j'avais réellement besoin.

mais il y a quelques sorties d'utilisateur sélectives que je veux afficher à la fois dans la console et dans le fichier log. Mais en raison du code ci-dessus, je ne suis pas en mesure de le faire.

je sais que si je supprime le code ci-dessus je peux obtenir le résultat désiré pour ce cas, mais je vais devoir écrire manuellement toutes les autres sorties dans le fichier journal qui n'est pas une tâche facile.

y a-t-il un moyen d'obtenir la sortie à la fois dans la console et dans le fichier journal sans supprimer les codes ci-dessus?

62
demandé sur bvidal 2013-08-27 12:06:17

9 réponses

exec 3>&1 1>>${LOG_FILE} 2>&1

enverrait la sortie stdout et stderr dans le fichier journal, mais vous laisserait aussi avec fd 3 connecté à la console, de sorte que vous pouvez faire

echo "Some console message" 1>&3

pour écrire un message uniquement sur la console, ou

echo "Some console and log file message" | tee /dev/fd/3

pour écrire un message à à la fois la console et le fichier journal - tee envoie sa sortie à la fois son propre fd 1 (qui est ici le LOG_FILE ) et le fichier vous lui avez dit d'écrire (qui est ici fd 3, c'est à dire la console).

exemple:

exec 3>&1 1>>${LOG_FILE} 2>&1

echo "This is stdout"
echo "This is stderr" 1>&2
echo "This is the console (fd 3)" 1>&3
echo "This is both the log and the console" | tee /dev/fd/3

serait imprimé

This is the console (fd 3)
This is both the log and the console

sur la console et mettre

This is stdout
This is stderr
This is both the log and the console

dans le fichier journal.

76
répondu Ian Roberts 2013-08-27 10:48:24

Oui, vous voulez utiliser tee :

tee - lire l'entrée standard et d'écrire sur la sortie standard, et les fichiers

simplement pipe votre commande pour tee et passer le dossier comme un argument, comme ainsi:

exec 1 | tee ${LOG_FILE}
exec 2 | tee ${LOG_FILE}

cela permet à la fois d'Imprimer la sortie vers le STDOUT et d'écrire la même sortie dans un fichier journal. Pour en savoir plus, lisez la section man tee .

notez que ceci n'écrira pas stderr au fichier journal, donc si vous voulez combiner les deux flux, utilisez:

exec 1 2>&1 | tee ${LOG_FILE}
31
répondu Jon Cairns 2013-08-27 08:09:10

j'ai essayé la réponse de joonty, mais j'ai aussi eu le

exec: 1: non trouvé

"151920920 d'erreur". C'est ce qui fonctionne le mieux pour moi ( confirmé travailler en zsh aussi):

#!/bin/bash
LOG_FILE=/tmp/both.log
exec > >(tee -a ${LOG_FILE} )
exec 2> >(tee -a ${LOG_FILE} >&2)
echo "this is stdout"
chmmm 77 /makeError

Le fichier /tmp/les deux.log after contient

this is stdout
chmmm command not found 

Le /tmp/les deux.le journal est ajouté, sauf si vous supprimez l'un de té.

21
répondu alfonx 2017-05-23 12:18:23

pour le fichier journal vous pouvez dater pour entrer dans les données de texte. le code suivant peut vous aider

# declaring variables

Logfile="logfile.txt"   
MAIL_LOG="Message to print in log file"  
Location="were is u want to store log file"

cd $Location   
if [ -f $Logfile ]  
then   
echo "$MAIL_LOG " >> $Logfile

else        

touch $Logfile   
echo "$MAIL_LOG" >> $Logfile    

fi  

sortie: 2. Le fichier de journalisation sera créé lors de la première exécution et sera mis à jour lors des prochaines éditions. Dans le cas où le fichier journal manque dans l'exécution future , script va créer un nouveau fichier journal.

3
répondu user2197712 2013-08-27 10:47:16

je voulais afficher les journaux sur stdout et le fichier journal avec l'horodatage. Aucune des réponses ci-dessus n'a fonctionné pour moi. J'ai utilisé la commande substitution de processus et exec et j'ai trouvé le code suivant.

2017-06-21 11:16:41+05:30 Fetching information about files in the directory...

ajouter les lignes suivantes en haut de votre script:

LOG_FILE=script.log
exec > >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done)
exec 2> >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done >&2)

Espérons que cela aide quelqu'un!

3
répondu Jyoti Dhiman 2017-06-21 05:57:00

j'ai trouvé un moyen d'obtenir le résultat souhaité. Si elle peut être peu orthodoxe. De toute façon ici il va. Dans la redir.j'ai le code suivant:

#####redir.env#####    
export LOG_FILE=log.txt

      exec 2>>${LOG_FILE}

    function log {
     echo "">>${LOG_FILE}
    }

    function message {
     echo ""
     echo "">>${LOG_FILE}
    }

puis dans le script actuel j'ai les codes suivants:

#!/bin/sh 
. redir.env
echo "Echoed to console only"
log "Written to log file only"
message "To console and log"
echo "This is stderr. Written to log file only" 1>&2

Ici echo sorties de la console, journal sorties à seulement fichier journal et message sorties à la fois le fichier journal et console.

après avoir exécuté le fichier de script ci-dessus, j'ai les sorties suivantes:

dans la console

en console



" Pour consoler et enregistrer

pour le fichier journal

Dans Le Fichier Log Écrit dans le fichier journal seulement

C'est stderr. Écrit dans le fichier journal seulement

Pour consoler et enregistrer

Espérons que cette aide.

1
répondu abinash shrestha 2013-08-30 05:17:17
    #
    #------------------------------------------------------------------------------
    # echo pass params and print them to a log file and terminal
    # with timestamp and $host_name and "151900920" PID
    # usage:
    # doLog "INFO some info message"
    # doLog "DEBUG some debug message"
    # doLog "WARN some warning message"
    # doLog "ERROR some really ERROR message"
    # doLog "FATAL some really fatal message"
    #------------------------------------------------------------------------------
    doLog(){
        type_of_msg=$(echo $*|cut -d" " -f1)
        msg=$(echo "$*"|cut -d" " -f2-)
        [[ $type_of_msg == DEBUG ]] && [[ $do_print_debug_msgs -ne 1 ]] && return
        [[ $type_of_msg == INFO ]] && type_of_msg="INFO " # one space for aligning
        [[ $type_of_msg == WARN ]] && type_of_msg="WARN " # as well

        # print to the terminal if we have one
        test -t 1 && echo " [$type_of_msg] `date "+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$] ""$msg"

        # define default log file none specified in cnf file
        test -z $log_file && \
            mkdir -p $product_instance_dir/dat/log/bash && \
                log_file="$product_instance_dir/dat/log/bash/$run_unit.`date "+%Y%m"`.log"
        echo " [$type_of_msg] `date "+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$] ""$msg" >> $log_file
    }
    #eof func doLog
1
répondu Yordan Georgiev 2017-07-25 08:47:29

je trouve très utile d'ajouter stdout et stderr à un fichier log. J'ai été heureux de voir une solution par alfonx avec exec > >(tee -a) , parce que je me demandais comment accomplir ceci en utilisant exec . J'ai trouvé une solution créative en utilisant la syntaxe here-doc et . : https://unix.stackexchange.com/questions/80707/how-to-output-text-to-both-screen-and-file-inside-a-shell-script

j'ai découvert qu'en zsh, le here-doc la solution peut être modifiée en utilisant la construction" multios "pour copier la sortie vers stdout/stderr et le fichier journal:

#!/bin/zsh
LOG="151900920".log
# 8 is an arbitrary number;
# multiple redirects for the same file descriptor 
# triggers "multios"
. 8<<\EOF /dev/fd/8 2>&2 >&1 2>>$LOG >>$LOG
# some commands
date >&2
set -x
echo hi
echo bye
EOF
echo not logged

Il n'est pas aussi lisible que le exec solution, mais il a l'avantage de permettre de vous connecter qu'une partie du script. Bien sûr, si vous omettez L'EOF, alors le script entier est exécuté avec logging. Je ne suis pas sûr comment zsh implémente multios, mais il peut avoir moins de frais généraux que tee . Malheureusement, il semble qu'on ne peut pas utilisez multios avec exec .

0
répondu Metamorphic 2017-04-13 12:36:24

essayez ceci, il fera le travail:

log_file=$curr_dir/log_file.txt
exec > >(tee -a ${log_file} )
exec 2> >(tee -a ${log_file} >&2)
0
répondu amousa 2017-07-07 00:45:39