Par exemple :
TAR=`tar -czvf /home/MonHome.tar.gz /tmp/ 2>> $LOGDIR`
Lorsque je lance à la main le script, tar est très polie et il me dit :
tar: Retrait de « / » de tête des noms des membres
Si je vais voir dans le fichier log que j'ai défini dans la variable j'ai en vrac la ligne tar: Retrait de « / » de tête des noms des membres alors que pour le reste des messages (ceux que je gère par les codes erreurs $?) j'ai défini un affichage comme ça :
jan 30 15:52:ss hostname backup[PID]: Erreur bidule chose
Moi ce que je voudrais c'est pouvoir mettre dans une variable toute sortie généré par une commande pour avoir des logs comme ça :
jan 30 15:52:ss hostname backup[PID]: Erreur machin truc
jan 30 15:52:ss hostname[PID]: tar: Retrait de « / » de tête des noms des membres
Vous avez une idée ?
Merci d'avance.
Philippe.
# récupérer la sortie de tar
Posté par sylvain cresto (site web personnel) . Évalué à 1.
SORTIE=`tar -czvf /home/MonHome.tar.gz /tmp/ 2>&1`
Tu as dans $SORTIE ce que t'a renvoyé la commande tar.
echo $SORTIE
# à l'envers ;-)
Posté par Steve Azriel . Évalué à 3.
Je verrais bien une solution "à l'envers" à ton problème :P
Comme tu n'as pas forcément besoin immédiatement de la sortie de la commande tar pour tes logs, c'est celle-ci que j'enverrais dans un fichier temporaire.
Après, il suffit de lire les messages stderr et de les formatter comme bon te semble.
Voici ce que cela donnerait (à tester !):
# Je crée un fichier temporaire
sortie_de_tar=$(mktemp -q)
if [ ${?} -ne 0 ]; then
echo Pas de bol '!'
fi
# Je lance l'archivage (attention a l'ordre des redirections !)
tar -czvf /home/MonHome.tar.gz /tmp/ 2>&1 >"${sortie_de_tar}" \
| while read ligne_erreur; do
# Ici, formattage de la ligne
echo $(date) $(hostname) ${ligne_erreur} >> "${LOGDIR}"
done
# Après, soit:
TAR=$(< "${sortie_de_tar}")
# ou
TAR=$(cat "${sortie_de_tar}")
# Petit ménage
rm "${sortie_de_tar}"
# La suite ici...
Qu'en penses tu ?
Bon courage !
Cdlt,
[^] # Re: à l'envers ;-)
Posté par santos . Évalué à 1.
Un des avantages étant que si le programme échoue au milieu de l'exécution (disque dur plein, coupure de courant, etc...), tu peux quand-même consulter les logs.
[^] # Re: à l'envers ;-)
Posté par Philippe M (site web personnel) . Évalué à 1.
Voila un bout de mon script :
Born to Kill EndUser !
[^] # Re: à l'envers ;-)
Posté par Philippe M (site web personnel) . Évalué à 1.
J'ai réussi à adapter ton idée à mon script mais j'ai un petit pour la récupération de la date/heure. Ton idée est de mettre dans un fichier les messages brut, ensuite de lire ce fichier, le modifier selon mes besoins et de l'écrire dans les logs. Ca marche nikel pour les messages que je génère puisqu'a la limite je les écrits directement dans les logs sous la forme plus ou moins standard. Au contraire pour les messages renvoyés par les commandes, par exemple
Ca va bien écrire les infos dans le fichier temporaire. Ensuite je relis le fichier temporaire par :
Le hic est au niveau de DATE_LOG, ca me récupère la date/heure du moment ou je lance write_log et non le moment où la ligne à été écrite dans le fichier temporaire. La solution, stocker dans ce fichier la date/heure d'écriture du message mais le hic est que je ne sais pas trop comment faire.
Philippe.
Born to Kill EndUser !
[^] # Re: à l'envers ;-)
Posté par Steve Azriel . Évalué à 1.
D'où mon idée "à l'envers" pour traiter ton problème :-)
Après moult relectures (et à tête reposée), je n'ai pas été assez "clair" dans mon explication :/
Voici ce que je te propose pour une commande lancée avec les bonnes redirections (cf message précédent) :
1) lire les logs stderr "au fil de l'eau" pour les formatter comme bon te semble via une boucle while read
2) renvoyer la sortie stdout (qui liste les fichiers archivés dans le tar) dans un fichier (temporaire).
=> Ainsi, tu formatteras chaque ligne d'erreur de la commande avec l'ajout du timestamp "au plus proche" de l'arrivé du message.
Ensuite, tu récupères la liste des fichiers dans ta variable shell pour faire ton traitement dessus.
[humour]
Bien sûr, je ne peux te certifier de la précision de l'horodatage des messages car je n'ai pas prise sur l'ordonnancement des processus de ton serveur ^__^, mais, à priori, dans des conditions normales, cela devrait convenir :-)
... (à suivre)
[/humour]
Bon courage !
Cdlt,
[humour]
... (suite)
PS: Si tu veux assurer un peu plus de précision, voici des pistes:
1) augmenter virtuellement la priorité de ton shell en diminuant la priorité de la commande tar (man nice)
Par exemple: nice -n 19 tar ... | while read
2) passer à un Linux Temps Réel
[/humour]
[^] # Re: à l'envers ;-)
Posté par Philippe M (site web personnel) . Évalué à 1.
Au contraire c'est assez lourd au niveau du script puisque pour toute les commandes pouvant générer une erreur je dois faire le while read... N'y a t'il pas un moyen de renvoyer la sauce vers une fonction qui elle est chargé de faire le while ?
Par exemple :
TAR=`tar -czvf /tmp/MonHome.tar.gz /home/MonHome` 2>&1 > 'MaFonctionQuiVaBien'
et la fonction
MaFonctionQuiVaBien() {
cat "${1}" | while read LIGNE_ERREUR
do
echo "${DATE_LOG} ${HOSTNAME} backupeur[$$]: ${LIGNE_ERREUR}" >> ${LOGDIR}
done
Born to Kill EndUser !
[^] # Re: à l'envers ;-)
Posté par Philippe M (site web personnel) . Évalué à 1.
Maintenant j'en suis à :
HOSTNAME=`hostname`
date_log () {
DATE_LOG=`date +%b" "%d" "%T`
}
write_log() {
date_log
echo "${1}" | while read LIGNE_ERREUR do
do
echo "${DATE_LOG} ${HOSTNAME} backupeur[$$]: ligne :${LIGNE_ERREUR}" >> /tmp/tar.log
done
}
date_log
MKTEMP=$(mktemp -q)
tar -czf /tmp/net.tar.gz /ne 2>&1 | write_log
rm -f ${MKTEMP}
Ca marche presque, après le | le script va bien dans la fonction write_log mais au contraire je ne sais pas comment lui faire comprendre au moment de l'appel que write_log doit prendre la sortie (out ou err) de tar. J'ai essayé en mettant tar dans une variable et ensuite de mettre ma variable en paramètre pour la fonction mais ça donne rien.
Born to Kill EndUser !
[^] # Re: à l'envers ;-)
Posté par Steve Azriel . Évalué à 1.
Le fichier temporaire créé via mktemp sert à stocker (temporairement) la sortie de la commande, pour laquelle aucun traitement immédiat n'est nécessaire.
Ainsi, après avoir "redirigé" les écritures sur 2(stderr) vers là où est écrit la sortie 1(stdout), tu peux faire de même en envoyant 1(stdout) vers le fichier temporaire.
L'important est de conserver l'ordre des redirections sinon ca ne fait pas ce que l'on souhaite :-)
Une fois que la commande est terminée et que write_log a fini, tu peux lire le contenu du fichier temporaire pour le charger dans une variable (dans ton exemple initial, il s'agissait de TAR).
En espérant avoir pu éclaircir les dernières ambigüités de mon premier commentaire ^__^
Bon courage !
Cdlt,
PS: Pour donner une solution à ton problème, voici le code que je propose et qui utilise un "wrapper" (A TESTER !).
Par avance, je vous remercie pour votre indulgence:
# Les constantes
# HOSTNAME - Nom de la machine
declare -r HOSTNAME="${HOSTNAME:-$(hostname)}"
function execute_et_log_stderr {
# Argument 1: Le fichier de log ou /dev/null :-)
local -r log_stderr="${1:-/dev/null}"
shift
# Une ressource temporaire pour stdout
local -r cmd_stdout=$(mktemp -q)
if [ ${?} -ne 0 ]; then
echo Impossible d"'"allouer une ressource temporaire '!'
return 255
fi
${@} 2>&1 1>"${cmd_stdout}" \
| while read cmd_stderr; do
echo "$(date +%b" "%d" "%T) ${HOSTNAME} backupeur[$$]: ligne :${cmd_stderr}"
done >> ${log_stderr}
cat ${cmd_stdout} && rm -f ${cmd_stdout}
return 0
}
# La pas de log de stderr
SANS_LOG=$(execute_et_log_stderr "" ls -al /home)
# La, il y aura log de stderr dans ${LOGFILE}
LOG_FILE=/var/log/backupeur
AVEC_LOG=$(execute_et_log_stderr "${LOGFILE}" tar -czf /tmp/net.tar.gz /ne)
PS2: Tiens, je revois presque le code proposé à mon premier post :P
PS3: Promis, j'arrête ! C'est mon dernier post sur cette demande (H)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.