102 votes

Comment puis-je enregistrer toutes les actions de bash scripts ?

À partir de la sortie de mon script, je veux capturer TOUTES les données des journaux avec les messages d'erreur et les rediriger toutes vers le fichier journal.

J'ai script comme ci-dessous :

#!/bin/bash
(
echo " `date` : part 1 - start "
ssh -f admin@server.com 'bash /www/htdocs/server.com/scripts/part1.sh logout exit'
echo " `date` : sleep 120"
sleep 120
echo " `date` : part 2 - start"
ssh admin@server.com 'bash /www/htdocs/server.com/scripts/part2.sh logout exit'
echo " `date` : part 3 - start"
ssh admin@server.com '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 echo commandement.

Comment vérifier dans les journaux que 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.

2voto

tom Points 11

TL;DR - Hier, j'ai écrit un ensemble d'outils pour enregistrer les exécutions de programmes et les sessions.

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 trucs. Le plus simple est d'utiliser le programme "script" comme xX0v0Xx l'a mentionné. J'ai trouvé que l'appel à script (sans aucun argument) me faisait souvent écraser la sortie d'un script précédent. J'ai donc créé cet alias. Tout ce qu'il fait est d'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 génial lorsque 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 les timestamps 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 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 lancez votre commande avec justlog (ou timelog), et ensuite vous utilisez simplement lesslog ou viewlog (je vais probablement créer un log emacs pour ces personnes) :

justlog run rcn rcn-work\\\\\* 'ps -ef -o lstart,cmd | grep [s]upervisor'
lesslog run

C'est ça, pas de ls ~/tmp , pas de jeux de complétion de tabulation pour trouver le nom du fichier. Il suffit de lancer lesslog (ou viewlog si vous aimez utiliser vim pour regarder les logs).

Mais, attendez ! Ce n'est pas tout !

"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 de tous les fichiers /etc/cron.d/atop du serveur 800 qui sont cassés :

justlog fordcrun 'cat /etc/cron.d/atop; md5dum /etc/cron.d/atop'

Ensuite, obtenez les noms d'hôtes (sur la ligne au-dessus de la sortie dans le 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

2voto

user411313 Points 1920

J'ai trouvé que le @nicerobot ( Comment puis-je enregistrer toutes les actions de bash scripts ? ) pourrait ne pas être suffisante pour complètement redirige toutes les sorties vers la console. Certaines sorties peuvent encore être perdues.

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 :

  1. Il ne suffit pas de rediriger la sortie car il faut encore rediriger l'interne echo appelle à la fois à la console et au fichier, donc le pipe-plus-tee est le seul moyen de diviser le flux de sortie.
  2. Nous devons utiliser (...) pour rediriger chaque flux vers un fichier autonome ou pour restaurer tous les flux vers l'original par étapes séparées. La deuxième raison est que myfoo Les appels avant l'auto-réentrée doivent fonctionner tels quels, sans redirection supplémentaire.
  3. Parce que le script peut être appelé à partir d'un script imbriqué, alors nous devons rediriger la sortie dans un fichier seulement une fois dans un appel de niveau supérieur. Nous utilisons donc NEST_LVL variable pour indiquer le niveau d'appel du nid.
  4. Parce que la redirection peut être exécutée de manière externe indépendamment du script, nous devons alors activer explicitement la redirection interne par l'intermédiaire de l'attribut IMPL_MODE variable.
  5. Nous devons utiliser les valeurs de date et d'heure pour créer automatiquement un nouveau fichier journal unique à chaque exécution de script.

1voto

Jose Tavares Points 11

Vous pouvez simplement utiliser "script".

man script pour les détails.

Exemple :

script -a -e -c "set -x; echo this is logging ..; <your script can be called here>" mylogfile.log

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X