É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?
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.
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}
j'ai essayé la réponse de joonty, mais j'ai aussi eu le
"151920920 d'erreur". C'est ce qui fonctionne le mieux pour moi ( confirmé travailler en zsh aussi):exec: 1: non trouvé
#!/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é.
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.
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!
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.
#
#------------------------------------------------------------------------------
# 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
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
.
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)