Cron job stderr pour envoyer un mail ET un fichier journal?

J’ai un job cron:

$SP_s/StartDailyS1.sh >$LP_s/MirrorLogS1.txt 

SP_s est le chemin du script et LP_s est le chemin du fichier journal. Cela envoie stdout au fichier journal et stderr à mon email.

Comment puis-je:
1) envoyer à la fois stdout AND stderr au fichier journal,
2) ET envoyer stderr à email

ou pour le dire autrement: stderr vers le fichier journal et le courrier électronique, et stdout uniquement vers le fichier journal.

MISE À JOUR: Aucune des réponses que j’ai obtenues jusqu’à présent, soit suivre les critères que j’ai définis, soit sembler convenir à un travail CRON.

J’ai vu ceci, qui est destiné à “envoyer le STDOUT et le STDERR d’une commande à un fichier, puis juste STDERR à un autre fichier” (posté par zazzybob sur unix.com), qui semble proche de ce que je veux faire et je me demandais si cela inspirerait quelqu’un de plus intelligent que moi:

 (( my_command 3>&1 1>&2 2>&3 ) | tee error_only.log ) > all.log 2>&1 

Je veux que cron envoie STDERR à un email plutôt qu’à un autre fichier.

Je ne sais pas pourquoi personne n’a mentionné cela.

Avec CRON, si vous spécifiez MAILTO = dans la crontab des utilisateurs, STDOUT est déjà envoyé par courrier.

Exemple

 [temp]$ sudo crontab -u user1 -l SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=user1 # transfer order shipping file every 3 minutes past the quarter hour 3,19,33,48 * * * * /home/user1/.bin/trans.sh 

Comme je ne faisais que regarder la page d’information pour le tee (essayer de comprendre comment faire la même chose), je peux répondre à la dernière partie de la question.

C’est la plupart du temps là:

 (( my_command 3>&1 1>&2 2>&3 ) | tee error_only.log ) > all.log 2>&1 

mais remplacez “error_only.log” par “> (email_command)”

 (( my_command 3>&1 1>&2 2>&3 ) | tee >(/bin/mail -s "SUBJECT" "EMAIL") ) > all.log 2>&1 

Note: selon les documents de tee, cela fonctionnera dans bash, mais pas dans / bin / sh. Si vous mettez ceci dans un script cron (comme dans /etc/cron.daily/) alors vous pouvez juste mais #! / Bin / bash en haut. Cependant, si vous le mettez en une seule ligne dans une crontab, vous devrez peut-être l’envelopper dans bash -c “”

Si vous pouvez faire avec stdout / err dans des fichiers séparés, ceci devrait faire:

 ($SP_s/StartDailyS1.sh 2>&1 >$LP_s/MirrorLogS1.txt.stdout) | tee $LP_s/MirrorLogS1.txt.stderr 

A moins que je ne manque quelque chose:

 command 2>&1 >> file.log | tee -a file.log 

2> & 1 redirige stderr vers stdout

>> redirige la commande standard stdout vers le fichier journal

| tee duplique stderr (de 2> & 1) vers le fichier journal et le transmet à stdout par courrier électronique à MAILTO

Je l’ai testé avec

 (echo Hello & echo 1>&2 World) 2>&1 >> x | tee -ax 

Qui montre en effet le monde dans la console et les deux textes dans x

La chose la plus moche est le nom de fichier en double. Et la mise en mémoire tampon différente de stdout / stderr pourrait rendre le texte dans file.log un peu compliqué, je suppose.

Un peu difficile si vous voulez que stdout et stderr soient combinés dans un seul fichier, avec stderr encore dans son propre stream.

Cela devrait le faire (vérification des erreurs, nettoyage et robustesse généralisée omis):

 #! /bin/sh CMD=..../StartDailyS1.sh LOGFILE=..../MirrorLogS1.txt FIFO=/tmp/fifo >$LOGFILE mkfifo $FIFO 2>/dev/null || : tee < $FIFO -a $LOGFILE >&2 & $CMD 2>$FIFO >>$LOGFILE 

stderr est envoyé à un canal nommé, saisi par tee(1) où il est ajouté au fichier journal (où est également ajouté le stdout de votre commande) et renvoyé à stderr normal.

Mon expérience (ubuntu) est que «crontab» ne contient que les emails ‘stderr’ (j’ai la sortie dirigée vers un fichier journal qui est ensuite archivé). C’est utile, mais je voulais une confirmation de l’exécution du script (même en l’absence d’erreurs sur ‘stderr’) et quelques détails sur le temps nécessaire, ce qui est un bon moyen de détecter les problèmes potentiels.

J’ai trouvé le moyen le plus simple de résoudre ce problème en écrivant le script avec quelques «échos» en double. Les nombreux échos réguliers se retrouvent dans le fichier journal. Pour les bits de non-erreur importants que je veux dans mon email crontab ‘MAILTO’, j’ai utilisé un ‘echo’ qui est dirigé vers stderr avec ‘1> & 2’.

Donc ceci:

  Frmt_s="+>>%y%m%d %H%M%S($HOSTNAME): " # =Format of timestamp: "(): " echo `date "$Frmt_s"`"'$0' started." # '$0' is path & filename echo `date "$Frmt_s"`"'$0' started." 1>&2 # message to stderr # REPORT: echo "" echo "================================================" echo "================================================" 1>&2 # message to stderr TotalMins_i=$(( TotalSecs_i / 60 )) # calculate elapsed mins RemainderSecs_i=$(( TotalSecs_i-(TotalMins_i*60) )) Title_s="TOTAL run time" Summary_s=$Summary_s$'\n'$(printf "%-20s%3s:%02d" "$Title_s" $TotalMins_i $RemainderSecs_i) echo "$Summary_s" echo "$Summary_s" 1>&2 # message to stderr echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 1>&2 # message to stderr echo "" echo `date "$Frmt_s"`"TotalSecs_i: $TotalSecs_i" echo `date "$Frmt_s"`"'$0' concluded." # '$0' is path & filename echo `date "$Frmt_s"`"'$0' concluded." 1>&2 # message to stderr 

Envoie-moi un email contenant ceci (quand il n’y a pas d’erreurs, les lignes commençant par ‘ssh:’ et ‘rsync:’ n’apparaissent pas):

 170408 030001(sb03): '/mnt/data1/LoSR/backup_losr_to_elwd.sh' started. ssh: connect to host 000.000.000.000 port 0000: Connection timed out rsync: connection unexpectedly closed (0 bytes received so far) [Receiver] rsync error: unexplained error (code 255) at io.c(226) [Receiver=3.1.0] ssh: connect to host 000.000.000.000 port 0000: Connection timed out rsync: connection unexpectedly closed (0 bytes received so far) [Receiver] rsync error: unexplained error (code 255) at io.c(226) [Receiver=3.1.0] ================================================ S6 SUMMARY (mins:secs): 'Templates' 2:07 'Clients' 2:08 'Backups' 0:10 'Homes' 0:02 'NetAppsS6' 10:19 'TemplatesNew' 0:01 'S6Www' 0:02 'Aabak' 4:44 'Aaldf' 0:01 'ateam.ldf' 0:01 'Aa50Ini' 0:02 'Aadmin50Ini' 0:01 'GenerateTemplates' 0:01 'BackupScripts' 0:01 TOTAL run time 19:40 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 170408 031941(sb03): '/mnt/data1/LoSR/backup_losr_to_elwd.sh' concluded. 

Cela ne satisfait pas mon désir initial de “envoyer à la fois stdout AND stderr au fichier journal” (stderr, et seules les lignes avec “1> & 2” vont à l’email; stdout va au journal), mais je Je trouve que c’est mieux que ma solution initialement imaginée, car le courrier électronique me trouve et je n’ai pas à chercher de problèmes dans le fichier journal.

Je pense que la solution serait:

 $SP_s/StartDailyS1.sh 2>&1 >> $LP_s/MirrorLogS1.txt | tee -a $LP_s/MirrorLogS1.txt 

Cette volonté:

  • append une sortie standard à $LP_s/MirrorLogS1.txt
  • append une erreur standard à $LP_s/MirrorLogS1.txt
  • erreur standard d’impression, de sorte que cron envoie un mail en cas d’erreur

Je suppose que vous utilisez bash, vous redirigez stdout et stderr comme ça

 1> LOG_FILE 2> LOG_FILE 

envoyer un mail contenant le stderr dans le corps quelque chose comme ça

 2> MESSAGE_FILE /bin/mail -s "SUBJECT" "EMAIL_ADDRESS" < MESSAGE_FILE 

Je ne sais pas si vous pouvez faire ce qui précède dans un seul passage

 /bin/mail -s "SUBJECT" "EMAIL_ADDRESS" <2 

Vous pouvez essayer d’écrire un autre cronjob pour lire le fichier journal et “afficher” le journal (laissez simplement Cron vous l’envoyer par e-mail)