À partir de la sortie de mon script, je veux capturer TOUTES les données des journaux avec des messages d'erreur et les rediriger toutes vers le fichier journal.
J'ai un script comme ci-dessous:
#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f [email protected] 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh [email protected] 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh [email protected] 'bash /www/htdocs/server.com/scripts/part3.sh logout exit'
echo " `date` : END"
) | tee -a /home/scripts/cron/logs
Je veux voir toutes les actions dans le fichier /home/scripts/cron/logs
Mais je ne vois que ce que j'ai mis après la commande echo
.
Comment vérifier dans les journaux que la commande SSH
a réussi?
J'ai besoin de rassembler tous les journaux. J'en ai besoin pour surveiller le résultat de chaque commande de mon script, pour mieux analyser ce qui se passe pendant que le script échoue.
Je mets généralement quelque chose de similaire au suivant au début de chaque script (surtout s'il s'exécute en tant que démon):
#!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>log.out 2>&1
# Everything below will go to the file 'log.out':
Explication:
exec 3>&1 4>&2
Enregistre les descripteurs de fichiers afin qu'ils puissent être restaurés à ce qu'ils étaient avant la redirection ou utilisés eux-mêmes pour sortir vers ce qu'ils étaient avant la redirection suivante.
trap 'exec 2>&4 1>&3' 0 1 2 3
Restaurer des descripteurs de fichiers pour des signaux particuliers. Pas généralement nécessaire car ils doivent être restaurés à la sortie du sous-shell.
exec 1>log.out 2>&1
Rediriger stdout
vers le fichier log.out
puis redirigez stderr
vers stdout
. Notez que l'ordre est important lorsque vous souhaitez qu'ils aillent dans le même fichier. stdout
doit être redirigé avant que stderr
soit redirigé vers stdout
.
À partir de là, pour voir la sortie sur la console (peut-être), vous pouvez simplement rediriger vers &3
. Par exemple,
echo "$(date) : part 1 - start" >&3
ira à l'endroit où stdout
a été dirigé, probablement la console, avant d'exécuter la ligne 3 ci-dessus.
pour obtenir la sortie ssh dans votre fichier journal, vous devez rediriger stderr
vers stdout
. vous pouvez le faire en ajoutant 2>&1
après votre script bash.
ça devrait ressembler à ça:
#!/bin/bash
(
...
) 2>&1 | tee ...
lorsque cela n'affiche pas les messages dans le bon ordre, essayez d'ajouter un autre sous-shell:
#!/bin/bash
((
...
) 2>&1) | tee ...
En lisant votre question, vous ne voulez pas enregistrer la sortie, mais toute la séquence de commandes, dans ce cas, les autres réponses ne vous aideront pas.
Appelez des scripts Shell avec -x pour tout afficher:
sh -x foo.sh
Connectez-vous au fichier que vous souhaitez avec:
sh -x foo.sh >> /home/scripts/cron/logs
En bash, vous pouvez mettre set -x
et il imprimera toutes les commandes qu'il exécute (et les variables bash) après cela. Vous pouvez le désactiver avec set +x
.
Si vous voulez être paranoïaque, vous pouvez mettre set -o errexit
dans votre script. Cela signifie que le script échouera et s'arrêtera si une commande a renvoyé un code de sortie différent de zéro, qui est le moyen standard unix de signaler que quelque chose s'est mal passé.
Si vous voulez obtenir de meilleurs journaux, vous devriez regarder ts
dans le paquet moreutils
debian/ubuntu. Il préfixera chaque ligne avec un horodatage et l'imprimera. Ainsi, vous pouvez voir quand les choses se produisent.
J'ai trouvé que la réponse @nicerobot ( Comment puis-je enregistrer toutes les actions des scripts bash? ) pourrait ne pas suffire pour complètement rediriger toutes les sorties vers la console. Certains résultats peuvent encore être perdus.
La redirection complète ressemble à ceci:
#!/bin/bash
# some basic initialization steps including `NEST_LVL` and `SCRIPTS_LOGS_ROOT variables...
source ".../__myinit__.sh"
# no local logging if nested call
(( ! IMPL_MODE && ! NEST_LVL )) && {
export IMPL_MODE=1
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' EXIT HUP INT QUIT RETURN
[[ ! -e "${SCRIPTS_LOGS_ROOT}/.log" ]] && mkdir "${SCRIPTS_LOGS_ROOT}/.log"
# RANDOM instead of milliseconds
case $BASH_VERSION in
# < 4.2
[123].* | 4.[01] | 4.0* | 4.1[^0-9]*)
LOG_FILE_NAME_SUFFIX=$(date "+%Y'%m'%d_%H'%M'%S''")$(( RANDOM % 1000 ))
;;
# >= 4.2
*)
printf -v LOG_FILE_NAME_SUFFIX "%(%Y'%m'%d_%H'%M'%S'')T$(( RANDOM % 1000 ))" -1
;;
esac
(
(
myfoo1
#...
myfooN
# self script reentrance...
exec $0 "$@"
) | tee -a "${SCRIPTS_LOGS_ROOT}/.log/${LOG_FILE_NAME_SUFFIX}.myscript.log" 2>&1
) 1>&3 2>&4
exit $?
}
(( NEST_LVL++ ))
# usual script body goes here...
Explication :
echo
vers la console et vers le fichier, donc le pipe-plus-tee est le seul moyen de diviser le flux de sortie.(...)
pour rediriger chaque flux vers un fichier autonome ou pour restaurer tous les flux vers l'original par des étapes distinctes. La deuxième raison parce que myfoo
appelle avant l'auto-réentrée doit fonctionner tel quel sans aucune redirection supplémentaire.NEST_LVL
variable pour indiquer le niveau d'appel imbriqué.IMPL_MODE
variable.Suite à ce que les autres ont dit, l'ensemble manuel est une bonne ressource. Je mets:
#!/usr/bin/env bash
exec 1> command.log 2>&1
set -x
En haut des scripts, je souhaite continuer, ou set -ex
s'il doit sortir en cas d'erreur.
TL; DR - Hier, j'ai écrit un ensemble d'outils pour enregistrer les exécutions et les sessions de programme.
Actuellement disponible sur https://github.com/wwalker/quick-log
En tant qu'administrateur, je veux toujours enregistrer la sortie d'une commande, souvent pas un script. Pour résoudre ce problème, j'ai écrit quelques choses. Le plus simple est d'utiliser le programme "script" comme mentionné xX0v0Xx. J'ai trouvé que l'appel de script (sans aucun argument) me faisait souvent écraser la sortie d'un script précédent. J'ai donc créé cet alias. Il ne fait qu'empêcher l'écrasement. Vous avez besoin d'un répertoire ~/tmp.
$ alias scr='script ~/tmp/TypeScript-$(date +%FT%T)'
$ scr
Script started, file is /home/wwalker/tmp/TypeScript-2019-12-05T18:56:31
$
C'est super quand je veux assister à une session interactive.
Lorsque je veux enregistrer la sortie d'une commande (script ou binaire), je veux soit la sortie exacte, soit la sortie avec des horodatages devant chaque ligne. J'ai donc écrit ces deux fonctions bash:
alias iso8601="date +%Y-%m-%dT%H:%M:%S"
justlog(){
name=$(basename "$1")
log=~/logs/${name}-$(iso8601)
"$@" > "$log" 2>&1
}
timelog(){
name=$(basename "$1")
log=~/logs/${name}-$(iso8601)
# https://github.com/wwalker/ilts
# You could replace ilts with ts
# /usr/bin/ts %FT%H:%M:%.S
"$@" |& ilts -S -E > "$log" 2>&1
}
Exécutez simplement votre commande comme vous le feriez normalement:
justlog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
ou
timelog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
Cela vient de créer 2 fichiers appelés:
wwalker@polonium:~ ✓ $ ls -l ~/logs/run*
-rw-r--r-- 1 wwalker wwalker 10495 2019-12-05 18:21:14.985 /home/wwalker/logs/run-2019-12-05T18:21:13
-rw-r--r-- 1 wwalker wwalker 1694 2019-12-05 18:24:02.878 /home/wwalker/logs/run-2019-12-05T18:24:01
-rw-r--r-- 1 wwalker wwalker 7623 2019-12-05 18:25:07.873 /home/wwalker/logs/run-2019-12-05T18:25:06
-rw-r--r-- 1 wwalker wwalker 10296 2019-12-05 18:34:59.546 /home/wwalker/logs/run-2019-12-05T18:34:57
Mais attendez, il y a plus!
Je ne voulais pas avoir à faire un ls pour trouver le nom du fichier journal que justlog ou timelog venait de créer pour moi. J'ai donc ajouté 3 fonctions supplémentaires:
newestlog(){
name=$(basename "$1")
ls ~/logs/"${name}"* | tail -1
}
viewlog(){
name=$(basename "$1")
view $( newestlog "$name" )
}
lesslog(){
name=$(basename "$1")
less $( newestlog "$name" )
}
Donc, vous exécutez votre commande avec justlog (ou timelog), puis vous utilisez simplement lesslog ou viewlog (je vais probablement créer un journal emacs pour ces personnes):
justlog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
lesslog run
C'est ça, non ls ~/tmp
, pas de jeux de tabulation pour trouver le nom du fichier. Exécutez simplement lesslog (ou viewlog si vous aimez utiliser vim pour consulter les journaux).
Mais attendez! Il y a plus!
"J'utilise grep tout le temps sur mes fichiers journaux" - Et la réponse est, vous l'avez deviné, greplog
Tout d'abord, récupérez le texte des fichiers /etc/cron.d/atop du serveur 800 qui sont cassés:
justlog fordcrun 'cat /etc/cron.d/atop; md5dum /etc/cron.d/atop'
Récupérez ensuite les noms d'hôtes (sur la ligne au dessus de la sortie du fichier :-)) avec greplog:
wwalker@polonium:~ ✓ $ greplog fordcrun -B1 -F "0 0 * * root"
int-salt-01:
0 0 * * root systemctl restart atop
--
rcn-pg-01:
0 0 * * root systemctl restart atop
rcn-pg-02:
0 0 * * root systemctl restart atop
rcn-pg-03:
0 0 * * root systemctl restart atop