Commit initial: récupération et tri rapide
This commit is contained in:
commit
a52829f96c
104 changed files with 11892 additions and 0 deletions
123
oldies/lib_gestion-mailinglists.sh
Normal file
123
oldies/lib_gestion-mailinglists.sh
Normal file
|
@ -0,0 +1,123 @@
|
|||
# Ici se trouvent réunies les fonctions et la configuration utiles au script
|
||||
# de gestion des mailing-lists
|
||||
|
||||
# Config
|
||||
LDAP_HOST="ldap.example.net"
|
||||
LDAP_ROOT="dc=example,dc=net"
|
||||
CONFIG_IDENTIFIANTS_SMBLDAP="/etc/smbldap-tools/smbldap_bind.conf"
|
||||
|
||||
. $CONFIG_IDENTIFIANTS_SMBLDAP
|
||||
LDAP_PASSWD="$masterPw"
|
||||
LDAP_BIND_DN="$masterDN"
|
||||
|
||||
|
||||
# Liste, sur stdout, les mailing-lists dont fait déjà parti l'adresse
|
||||
# email fournie en argument.
|
||||
# args: email
|
||||
#
|
||||
# note : effectué en connexion anonyme. A priori, les droits sont suffisants.
|
||||
afficher_abonnements_en_cours() {
|
||||
ldapsearch -x -h "$LDAP_HOST" -b "ou=mailing-lists,$LDAP_ROOT" -LLL "(rfc822MailMember=$1)" cn | sed -n 's/^cn: \(.*\)/\1/p' | sort
|
||||
}
|
||||
|
||||
# Affiche la liste des mailing-lists
|
||||
#
|
||||
# note : effectué en connexion anonyme. A priori, les droits sont suffisants.
|
||||
afficher_listing_mailinglists() {
|
||||
ldapsearch -x -h "$LDAP_HOST" -b "ou=mailing-lists,$LDAP_ROOT" -LLL cn | sed -n 's/^cn: \(.*\)/\1/p' | sort
|
||||
}
|
||||
|
||||
# Affiche la liste des abonnés d'une mailing-list
|
||||
# args: mailing-list
|
||||
#
|
||||
# note : effectué en connexion anonyme. A priori, les droits sont suffisants.
|
||||
afficher_abonnes_mailinglist() {
|
||||
ldapsearch -x -h "$LDAP_HOST" -b "cn=$1,ou=mailing-lists,$LDAP_ROOT" -LLL rfc822MailMember | sed -n 's/^rfc822MailMember: //p'
|
||||
}
|
||||
|
||||
# Supprime l'email d'une mailing-list
|
||||
# args: email, mailing-list
|
||||
supprimer_abonnement() {
|
||||
# Ecriture du mot de passe
|
||||
LDAP_PASSWDFILE=$( mktemp )
|
||||
printf "%s" "$LDAP_PASSWD" >$LDAP_PASSWDFILE
|
||||
|
||||
# Requete
|
||||
cat <<EOF | ldapmodify -x -h $LDAP_HOST -D "$LDAP_BIND_DN" -y "$LDAP_PASSWDFILE"
|
||||
dn: cn=$2,ou=mailing-lists,$LDAP_ROOT
|
||||
changetype: modify
|
||||
delete: rfc822MailMember
|
||||
rfc822MailMember: $1
|
||||
EOF
|
||||
RETOUR="$?"
|
||||
|
||||
# Effacement du mot de passe
|
||||
rm -f "$LDAP_PASSWDFILE"
|
||||
|
||||
return $RETOUR
|
||||
}
|
||||
|
||||
# Ajoute l'email à une mailing-list
|
||||
# args: email, mailing-list
|
||||
creer_abonnement() {
|
||||
# Ecriture du mot de passe
|
||||
LDAP_PASSWDFILE=$( mktemp )
|
||||
printf "%s" "$LDAP_PASSWD" >$LDAP_PASSWDFILE
|
||||
|
||||
# Requête
|
||||
cat <<EOF | ldapmodify -x -h $LDAP_HOST -D "$LDAP_BIND_DN" -y "$LDAP_PASSWDFILE"
|
||||
dn: cn=$2,ou=mailing-lists,$LDAP_ROOT
|
||||
changetype: modify
|
||||
add: rfc822MailMember
|
||||
rfc822MailMember: $1
|
||||
EOF
|
||||
RETOUR="$?"
|
||||
|
||||
# Effacement du mot de passe
|
||||
rm -f "$LDAP_PASSWDFILE"
|
||||
|
||||
return $RETOUR
|
||||
}
|
||||
|
||||
# Détruit une mailing-list
|
||||
# args: mailing-list
|
||||
supprimer_mailinglist() {
|
||||
# Ecriture du mot de passe
|
||||
LDAP_PASSWDFILE=$( mktemp )
|
||||
printf "%s" "$LDAP_PASSWD" >$LDAP_PASSWDFILE
|
||||
|
||||
# Requete
|
||||
cat <<EOF | ldapmodify -x -h $LDAP_HOST -D "$LDAP_BIND_DN" -y "$LDAP_PASSWDFILE"
|
||||
dn: cn=$1,ou=mailing-lists,$LDAP_ROOT
|
||||
changetype: delete
|
||||
EOF
|
||||
RETOUR="$?"
|
||||
|
||||
# Effacement du mot de passe
|
||||
rm -f "$LDAP_PASSWDFILE"
|
||||
|
||||
return $RETOUR
|
||||
}
|
||||
|
||||
# Crée une mailing-list
|
||||
# args: mailing-list
|
||||
creer_mailinglist() {
|
||||
# Ecriture du mot de passe
|
||||
LDAP_PASSWDFILE=$( mktemp )
|
||||
printf "%s" "$LDAP_PASSWD" >$LDAP_PASSWDFILE
|
||||
|
||||
# Requete
|
||||
cat <<EOF | ldapmodify -x -h $LDAP_HOST -D "$LDAP_BIND_DN" -y "$LDAP_PASSWDFILE"
|
||||
dn: cn=$1,ou=mailing-lists,$LDAP_ROOT
|
||||
changetype: add
|
||||
cn: $1
|
||||
objectClass: nisMailAlias
|
||||
objectClass: top
|
||||
EOF
|
||||
RETOUR="$?"
|
||||
|
||||
# Effacement du mot de passe
|
||||
rm -f "$LDAP_PASSWDFILE"
|
||||
|
||||
return $RETOUR
|
||||
}
|
114
oldies/sauvegarde_pfsense.sh
Executable file
114
oldies/sauvegarde_pfsense.sh
Executable file
|
@ -0,0 +1,114 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script sert à la sauvegarde de notre firewall pfSense
|
||||
# Très inspiré du script http://www.scribd.com/doc/92371725/pfsense
|
||||
|
||||
# Configuration
|
||||
BASE_DIR="$HOME/backups"
|
||||
PREFIXE="sauv_pfsense_"
|
||||
SUFFIXE=$( date +%Y%m%d-%H%M )
|
||||
DUREE_DE_VIE=0
|
||||
USERNAME="backuppc"
|
||||
PASSWORD="toto123"
|
||||
COOKIES_FILE=$( mktemp )
|
||||
CSRF_MAGIC=""
|
||||
|
||||
|
||||
# Arrêt à la première erreur non-catchée
|
||||
set -e
|
||||
|
||||
# Fonctions
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [-b base_dir] [-p prefixe] [-s suffixe] [-d duree_de_vie] hostname/IP
|
||||
$0 -h
|
||||
|
||||
-b base_dir : répertoire de sauvegarde (defaut: $BASE_DIR),
|
||||
-p prefixe : prefixe des fichiers de sauvegarde (defaut: $PREFIXE),
|
||||
-s suffixe : suffixe des fichiers de sauvegarde (default basé sur la date, ex: $SUFFIXE),
|
||||
-d duree_de_vie : age en nb de jours a partir duquel les anciennes archives sont supprimees. Si 0, pas de suppression. (defaut: $DUREE_DE_VIE),
|
||||
hostname/IP : nom d'hôte ou IP du firewall pfsense à sauvegarder.
|
||||
EOF
|
||||
}
|
||||
|
||||
clean_up_and_exit() {
|
||||
test -f "$COOKIES_FILE" && rm -f "$COOKIES_FILE"
|
||||
exit $1
|
||||
}
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts b:p:s:d:h o; do
|
||||
case $o in
|
||||
'b')
|
||||
BASE_DIR="$OPTARG"
|
||||
;;
|
||||
|
||||
'p')
|
||||
PREFIXE="$OPTARG"
|
||||
;;
|
||||
|
||||
's')
|
||||
SUFFIXE="$OPTARG"
|
||||
;;
|
||||
|
||||
'd')
|
||||
DUREE_DE_VIE="$OPTARG"
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
HOSTNAME_PFSENSE="$1"
|
||||
BASE_NAME=$( printf "%s" $( basename "$REPDRUPAL" ) | tr -c "a-zA-Z" "-" )
|
||||
|
||||
if [ -z "$HOSTNAME_PFSENSE" ]; then
|
||||
echo "ERREUR: veuillez indiquer un hostname (ou une IP)." >&2
|
||||
clean_up_and_exit 1
|
||||
fi
|
||||
if [ ! -d "$BASE_DIR" ]; then
|
||||
echo "ERREUR: repertoire de destination '$BASE_DIR' inexistant." >&2
|
||||
clean_up_and_exit 1
|
||||
fi
|
||||
|
||||
# Récupération du CSRF
|
||||
CSRF_MAGIC="$( wget -q -O - --keep-session-cookies --save-cookies "$COOKIES_FILE" https://$HOSTNAME_PFSENSE/index.php | sed -n "s/.*<input type='hidden' name='__csrf_magic' value=\"\([^\"]\+\)\".*/\1/p" || echo "" )"
|
||||
if [ -z "$CSRF_MAGIC" ]; then
|
||||
echo "ERREUR: erreur lors de la récupération du __csrf_magic." >&2
|
||||
clean_up_and_exit 1
|
||||
fi
|
||||
|
||||
# Authentification
|
||||
if ! wget -q -O /dev/null --keep-session-cookies --save-cookies "$COOKIES_FILE" --load-cookies "$COOKIES_FILE" --post-data "__csrf_magic=$CSRF_MAGIC&usernamefld=$USERNAME&passwordfld=$PASSWORD&login=Login" https://$HOSTNAME_PFSENSE/index.php; then
|
||||
echo "ERREUR: echec a la premiere connexion." >&2
|
||||
clean_up_and_exit 1
|
||||
fi
|
||||
|
||||
# On vérifie que l'on est bien connecté
|
||||
if [ $( wget -q -O - --keep-session-cookies --save-cookies "$COOKIES_FILE" --load-cookies "$COOKIES_FILE" https://$HOSTNAME_PFSENSE/diag_backup.php | grep -c "Diagnostics: Backup/restore" ) -lt 1 ]; then
|
||||
echo "ERREUR: impossible d'accéder à la page de backup." >&2
|
||||
clean_up_and_exit 1
|
||||
fi
|
||||
|
||||
#Config. seule
|
||||
wget -q -O "$BASE_DIR/$PREFIXE$BASE_NAME$HOSTNAME_PFSENSE-conf_$SUFFIXE.xml" --keep-session-cookies --save-cookies "$COOKIES_FILE" --load-cookies "$COOKIES_FILE" --post-data "Submit=Download%20configuration&donotbackuprrd=on" https://$HOSTNAME_PFSENSE/diag_backup.php
|
||||
#Config + données RRD
|
||||
wget -q -O "$BASE_DIR/$PREFIXE$BASE_NAME$HOSTNAME_PFSENSE-confrrd_$SUFFIXE.xml" --keep-session-cookies --save-cookies "$COOKIES_FILE" --load-cookies "$COOKIES_FILE" --post-data "Submit=Download%20configuration" https://$HOSTNAME_PFSENSE/diag_backup.php
|
||||
|
||||
# Suppression des vieux backups
|
||||
if [ "$DUREE_DE_VIE" -ne "0" ]; then
|
||||
find $BASE_DIR -name "$PREFIXE$BASE_NAME$HOSTNAME_PFSENSE-conf_*.xml" -mtime "+$DUREE_DE_VIE" -print0 | xargs -n 200 -r -0 rm -f
|
||||
find $BASE_DIR -name "$PREFIXE$BASE_NAME$HOSTNAME_PFSENSE-confrrd_*.xml" -mtime "+$DUREE_DE_VIE" -print0 | xargs -n 200 -r -0 rm -f
|
||||
fi
|
||||
|
||||
clean_up_and_exit 0
|
25
oldies/sauvegarde_samba.sh
Executable file
25
oldies/sauvegarde_samba.sh
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
# Le fichier sera nommé BASE_DIR/PREFIXEbasenameSUFFIXE
|
||||
BASE_DIR=/var/backups/bdd-samba
|
||||
PREFIXE=sauv_samba_
|
||||
SUFFIXE=_$( date +%Y%m%d-%H%M ).tar.gz
|
||||
DUREE_DE_VIE=100
|
||||
|
||||
# Vérifications initiales
|
||||
if [ ! -d "$BASE_DIR" ]; then
|
||||
echo "ERREUR : répertoire de sauvegarde inexistant : $BASE_DIR ." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Sauvegarde
|
||||
cd /var/lib
|
||||
tar -czf "$BASE_DIR/$PREFIXE"example.net"$SUFFIXE" samba
|
||||
|
||||
# Suppression des anciennes sauvegardes
|
||||
if [ "$1" = "--delete-olds" ]; then
|
||||
find $BASE_DIR -name "$PREFIXE*" -mtime +$DUREE_DE_VIE -print0 | xargs -n 200 -r -0 rm -f
|
||||
fi
|
||||
|
||||
|
242
oldies/script_ajout-utilisateur.sh
Executable file
242
oldies/script_ajout-utilisateur.sh
Executable file
|
@ -0,0 +1,242 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script aide à la création d'un compte LDAP
|
||||
# Il s'occupe :
|
||||
# - création LDAP/SMB
|
||||
# - mot de passe
|
||||
# - création de la boîte Cyrus
|
||||
# - ajout aux listes d'emails (salaries@example.net, ...)
|
||||
|
||||
# Ce script nécessite :
|
||||
# - des identifiants admin sur les listes emails (utilisation des identifiants smbldap pour l'instant. Pas glop.)
|
||||
# - des identifiants admin sur Cyrus. Ces identifiants seront contenus dans le fichier $CONFIG_IDENTIFIANTS_CYRUS, au format :
|
||||
# user=LOGIN
|
||||
# password=PASS
|
||||
|
||||
|
||||
# Config
|
||||
LDAP_HOST="ldap.example.net"
|
||||
LDAP_ROOT="dc=example,dc=net"
|
||||
CYRUS_HOST="messagerie.example.net"
|
||||
CONFIG_EMAIL_DOMAIN="example.net"
|
||||
CONFIG_DEFAULT_GID=513
|
||||
CONFIG_DEFAULT_QUOTA=1048576
|
||||
CONFIG_IDENTIFIANTS_SMBLDAP="/etc/smbldap-tools/smbldap_bind.conf"
|
||||
CONFIG_IDENTIFIANTS_CYRUS="/root/.cyrus_auth"
|
||||
|
||||
# Petite mise en bouche
|
||||
cat <<EOF
|
||||
Script de création d'un compte utilisateur dans l'annuaire LDAP et
|
||||
dans Cyrus (IMAP/POP3), puis d'inscription aux mailing-lists.
|
||||
|
||||
Dernière modification : 2010-09-30 (chl)
|
||||
(interruption possible via Ctrl-C)
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
# Fonctions (désolé pour la lisibilité, 'faut les définir au-dessus des appels)
|
||||
|
||||
check_string() {
|
||||
# Vérifie que la chaîne ne contient pas "trop" de caractères
|
||||
# spéciaux (accepte accents, espaces et tirets)
|
||||
# TODO
|
||||
test "$1" != ""
|
||||
}
|
||||
|
||||
check_email() {
|
||||
# Vérifie la syntaxe et l'unicité de l'adresse e-mail
|
||||
|
||||
# Recherche dans LDAP d'une adresse identique
|
||||
RACINE_EMAIL=$( echo "$1" | sed 's/@.*//g' )
|
||||
if [ $( ldapsearch -x -h "$LDAP_HOST" -b "ou=users,$LDAP_ROOT" -LLL "mailLocalAddress=$RACINE_EMAIL" | grep -c "^dn: " ) -gt 0 ]; then
|
||||
# Listing du(es) login(s) utilisant cette adresse
|
||||
TMP=$( ldapsearch -x -h "$LDAP_HOST" -b "ou=users,$LDAP_ROOT" -LLL "mailLocalAddress=$RACINE_EMAIL" uid | sed -n 's/^uid: //p' )
|
||||
echo "ERREUR: adresse email déjà utilisée par :" $TMP "." >&2
|
||||
|
||||
return 1
|
||||
fi
|
||||
|
||||
#TODO : vérif syntaxe
|
||||
test "$1" != ""
|
||||
}
|
||||
|
||||
check_login() {
|
||||
# n'accepte que les minuscules et les chiffres (doit commencer par une lettre)
|
||||
|
||||
# locale "C" pour que [a-z] ne contienne pas à, é, ...
|
||||
OLDLANG="$LANG"
|
||||
LANG="C"
|
||||
RETURN=0
|
||||
# Passage à la regexp de la mort
|
||||
if [ $( printf "%s" "$1" | egrep -c "^[a-z][a-z0-9]{2,7}$" ) -ne 1 ]; then
|
||||
RETURN=1
|
||||
# Si le login est vide, on reste clément et rien n'est affiché
|
||||
test -n "$1" && echo "ERREUR: login non valide (regexp: ^[a-z][a-z0-9]{2,7}$ )" >&2
|
||||
fi
|
||||
LANG="$OLDLANG"
|
||||
test "$RETURN" -eq 0 || return 1
|
||||
|
||||
# Vérification que le login (=uid LDAP) n'est pas déjà utilisé
|
||||
if [ $( ldapsearch -x -h "$LDAP_HOST" -b "ou=users,$LDAP_ROOT" -LLL "uid=$1" | grep -c "^dn: " ) -gt 0 ]; then
|
||||
echo "ERREUR: login déjà existant." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_unix_homedir() {
|
||||
# Rien à faire (?)
|
||||
test "$1" != "" # renvoie false si $1 vide
|
||||
}
|
||||
|
||||
generate_default_email() {
|
||||
# Initiale du prénom + nom
|
||||
RETURN=$( printf "%.01s%s@%s" "$1" "$2" "$CONFIG_EMAIL_DOMAIN" | tr "A-Z" "a-z" )
|
||||
|
||||
# Suppression des caractères spéciaux et sortie de la fonction
|
||||
LANG=C echo "$RETURN" | tr -dc "a-z0-9-.@"
|
||||
}
|
||||
|
||||
generate_default_login() {
|
||||
# on se base lâchement sur generate_default_email :)
|
||||
# (TODO : bugs divers si prénom + nom < 3 caractères...)
|
||||
printf "%.03s" $( generate_default_email "$1" "$2" )
|
||||
}
|
||||
|
||||
generate_default_unix_homedir() {
|
||||
# On renvoie simplement /home/LOGIN
|
||||
echo "/home/$1"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Enfin : le code...
|
||||
# 1ère étape : on demande interactivement toutes les infos
|
||||
# et on crée le compte + mot de passe
|
||||
|
||||
#Prénom
|
||||
while ! check_string "$PRENOM"; do
|
||||
printf "Prénom : "; read PRENOM
|
||||
done
|
||||
|
||||
#Nom
|
||||
while ! check_string "$NOM"; do
|
||||
printf "Nom : "; read NOM
|
||||
done
|
||||
|
||||
#login
|
||||
DEFAULT_LOGIN=$( generate_default_login "$PRENOM" "$NOM" )
|
||||
while ! check_login "$LOGIN"; do
|
||||
printf "Login [%s] : " "$DEFAULT_LOGIN"; read LOGIN
|
||||
test "$LOGIN" = "" && LOGIN="$DEFAULT_LOGIN"
|
||||
done
|
||||
|
||||
#email
|
||||
DEFAULT_EMAIL=$( generate_default_email "$PRENOM" "$NOM" )
|
||||
while ! check_email "$EMAIL"; do
|
||||
# Prompt avec proposition
|
||||
printf "Email [%s] : " "$DEFAULT_EMAIL"; read EMAIL
|
||||
# Si l'utilisateur laisse le champ vide : utilisation de la proposition
|
||||
test "$EMAIL" = "" && EMAIL="$DEFAULT_EMAIL"
|
||||
done
|
||||
|
||||
#Home directory (UNIX)
|
||||
DEFAULT_UNIX_HOMEDIR=$( generate_default_unix_homedir "$LOGIN" )
|
||||
while ! check_unix_homedir "$UNIX_HOMEDIR"; do
|
||||
printf "Homedir [%s] : " "$DEFAULT_UNIX_HOMEDIR"; read UNIX_HOMEDIR
|
||||
test "$UNIX_HOMEDIR" = "" && UNIX_HOMEDIR="$DEFAULT_UNIX_HOMEDIR"
|
||||
done
|
||||
|
||||
|
||||
# Création du compte avec smbldap-useradd + demande du mot de passe
|
||||
echo "Création du compte dans LDAP... (éviter le Ctrl-C à partir de maintenant)"
|
||||
if ! smbldap-useradd -a -g $CONFIG_DEFAULT_GID -M "$EMAIL" -N "$PRENOM" -S "$NOM" -d "$UNIX_HOMEDIR" "$LOGIN"; then
|
||||
echo "ERREUR: smbldap-useradd a renvoyé une erreur. Arrêt du script $0." >&2
|
||||
return 1
|
||||
fi
|
||||
echo "Compte LDAP créé."
|
||||
echo
|
||||
|
||||
# mot de passe
|
||||
echo "Veuillez renseigner le mot de passe..."
|
||||
TMP=""
|
||||
while test "$TMP" = "" && ! smbldap-passwd "$LOGIN"; do
|
||||
echo "WARNING: problème sur le mot de passe." >&2
|
||||
printf "Voulez-vous réessayer ? (O/n)"
|
||||
read TMP
|
||||
if [ $( echo "$TMP" | egrep -ic "^o$" ) -eq 1 ]; then
|
||||
TMP=""
|
||||
fi
|
||||
done
|
||||
echo
|
||||
|
||||
|
||||
# 2ème étape : création de la boîte mail dans Cyrus
|
||||
#
|
||||
# Tout se fait via un script Perl parce que les outils d'admin
|
||||
# de Cyrus sont pas franchement faciles à scripter...
|
||||
printf "Créer la boîte mail dans Cyrus ? (O/n)"
|
||||
read TMP
|
||||
if [ -n "$TMP" ] && [ $( echo "$TMP" | egrep -ic "^o$" ) -eq 0 ]; then
|
||||
echo "Ah bon ?! Ben à la prochaine alors." >&2
|
||||
return 0
|
||||
fi
|
||||
|
||||
RACINE_EMAIL=$( echo "$EMAIL" | sed 's/@.*//' )
|
||||
cat <<EOF | perl -MCyrus::IMAP::Admin
|
||||
# Connexion
|
||||
my \$conn = Cyrus::IMAP::Admin->new('$CYRUS_HOST') or die "Echec de connexion.";
|
||||
|
||||
# Lecture du fichier de configuration
|
||||
open CONFIG, '$CONFIG_IDENTIFIANTS_CYRUS';
|
||||
while (<CONFIG>) {
|
||||
chomp; # no newline
|
||||
s/^#.*//; # no comments
|
||||
s/^\s+//; # no leading white
|
||||
s/\s+$//; # no trailing white
|
||||
next unless length; # anything left?
|
||||
my (\$var, \$value) = split(/\s*=\s*/, \$_, 2);
|
||||
\$cyrus_config{\$var} = \$value;
|
||||
}
|
||||
|
||||
# Authentification
|
||||
\$conn->authenticate(
|
||||
"-user" => \$cyrus_config{'user'},
|
||||
"-password" => \$cyrus_config{'password'},
|
||||
"-mechanism" => 'LOGIN',
|
||||
) or die "Echec à l'authentification.";
|
||||
|
||||
# Création de la boîte Cyrus
|
||||
\$conn->create('user.$RACINE_EMAIL') or die "Echec à la création de la boîte ('va falloir aller voir à la main si qqchose a été fait...)";
|
||||
|
||||
# Spécification du quota
|
||||
\$conn->setquota('user.$RACINE_EMAIL', 'STORAGE', '$CONFIG_DEFAULT_QUOTA') or die "Echec lors de la mise en place du quota";
|
||||
EOF
|
||||
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Boîte créée."
|
||||
else
|
||||
echo "ERREUR: erreur à la création de la boîte. Le compte LDAP existe néamoins. Voir avec Cyrus. Abandon." >&2
|
||||
return 1
|
||||
fi
|
||||
echo
|
||||
|
||||
|
||||
# 3ème étape : les listes mails
|
||||
echo "Ajout aux mailing-lists..."
|
||||
if ! ./script_ml-gestion-abonne.sh -a salaries -i "$EMAIL"; then
|
||||
cat <<EOF >&2
|
||||
NOTICE: apparemment, il y a eu un pépin à la gestion des mailing-lists.
|
||||
Le compte est néanmoins créé, on vous laisse vous débrouiller avec
|
||||
./script_ml-gestion-abonne.sh ou PHPLDAPAdmin.
|
||||
|
||||
Cordialement.
|
||||
EOF
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 4ème étape : envoi du mail de bienvenue
|
||||
# TODO
|
||||
|
||||
|
||||
echo "Fin du script."
|
136
oldies/script_deploiement-massif-war.sh
Executable file
136
oldies/script_deploiement-massif-war.sh
Executable file
|
@ -0,0 +1,136 @@
|
|||
#!/bin/sh
|
||||
|
||||
RACINE_MULTIINSTANCES="/var/lib/tomcat7-multiinstances"
|
||||
RACINE_PATCHS="$HOME/patchs"
|
||||
WAR_FILE=""
|
||||
WEBAPP_NAME="ROOT"
|
||||
RELANCE_AUTO_TOMCAT=1
|
||||
JUST_TEST_THE_PATCHS=0
|
||||
|
||||
set -e
|
||||
|
||||
# Fonctions
|
||||
# fonction d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [options] -w package.war instance1 instance2 ...
|
||||
$0 -h
|
||||
|
||||
Ce script déploie un war dans les instances Tomcat indiquées
|
||||
puis les patchs en utilisant le fichier homonyme suffixé en .diff
|
||||
Par ex:
|
||||
$0 -w myapp-1.1.1.war tomcat7_003_titi tomcat7_008_toto
|
||||
va déployer 'myapp-1.1.1.war' dans la webapp ROOT des 2 instances, puis
|
||||
va appliquer les patchs tomcat7_003_titi.diff et tomcat7_008_toto.diff
|
||||
qui se trouvent dans '$RACINE_PATCHS'.
|
||||
|
||||
Ce script commence par tester chacun des patchs sur un dézippage temporaire
|
||||
du war, puis crée une copie par instance, la patche, éteint Tomcat, remplace
|
||||
l'ancienne webapp par la nouvelle copie patchée et reboote tomcat.
|
||||
|
||||
Options :
|
||||
-w : war à déployer
|
||||
-d : répertoire racine du multiinstances (par défaut : '$RACINE_MULTIINSTANCES')
|
||||
-D : répertoire contenant les patchs (par défaut : '$RACINE_PATCHS')
|
||||
-n : nom de la webapp à écraser (par défaut : '$WEBAPP_NAME')
|
||||
-T : juste tester les patchs sur le war, ne pas faire le déploiement
|
||||
|
||||
-h : this help screen
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts d:D:n:hTw: o; do
|
||||
case $o in
|
||||
'd')
|
||||
RACINE_MULTIINSTANCES="$OPTARG"
|
||||
;;
|
||||
|
||||
'D')
|
||||
RACINE_PATCHS="$OPTARG"
|
||||
;;
|
||||
|
||||
'n')
|
||||
WEBAPP_NAME="$OPTARG"
|
||||
;;
|
||||
|
||||
'T')
|
||||
JUST_TEST_THE_PATCHS=1
|
||||
;;
|
||||
|
||||
'w')
|
||||
# Utilisation de readlink pour avoir un chemin absolu,
|
||||
# vu qu'on bouge pas mal entre les répertoires :-/
|
||||
WAR_FILE="$( readlink -f "$OPTARG" )"
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
#REPDRUPAL="$1"
|
||||
|
||||
# Petites vérifs
|
||||
if [ ! -f "$WAR_FILE" ]; then
|
||||
echo "ERREUR: fichier '$WAR_FILE' introuvable." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérification des patchs
|
||||
echo "INFO: vérification des patchs..."
|
||||
# on dézippe le war dans un dossier temporaire
|
||||
TEMP_REP=$( mktemp -d )
|
||||
cd "$TEMP_REP"
|
||||
unzip -q "$WAR_FILE"
|
||||
# ... et on boucle sur chacun de patchs demandés
|
||||
for INSTANCE in $@; do
|
||||
echo "$INSTANCE"
|
||||
if [ ! -f $RACINE_PATCHS/$INSTANCE.diff ]; then
|
||||
echo "ERREUR: patch inexistant pour l'instance '$INSTANCE'." >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! patch --dry-run -p1 < $RACINE_PATCHS/$INSTANCE.diff; then
|
||||
echo "ERREUR: patch non applicable sur instance $INSTANCE." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
cd /
|
||||
rm -rf "$TEMP_REP"
|
||||
# Si on se contentait de tester les patchs, on s'arrête là
|
||||
[ "$JUST_TEST_THE_PATCHS" -eq 1 ] && exit 0
|
||||
|
||||
# Déploiement
|
||||
echo "INFO: déploiement..."
|
||||
for INSTANCE in $@; do
|
||||
echo "$INSTANCE"
|
||||
# Dézippage du war dans un dossier temporaire
|
||||
cd "$RACINE_MULTIINSTANCES/$INSTANCE"
|
||||
mkdir ROOT_new
|
||||
cd ROOT_new
|
||||
unzip -q "$WAR_FILE"
|
||||
# Patch de la copie dézippée
|
||||
patch -p1 < $RACINE_PATCHS/$INSTANCE.diff
|
||||
|
||||
# Relance de tomcat
|
||||
if [ "$RELANCE_AUTO_TOMCAT" -ne 0 ]; then
|
||||
service $INSTANCE stop
|
||||
sleep 3
|
||||
rm -rf "../webapps/$WEBAPP_NAME"
|
||||
mv -i ../ROOT_new "../webapps/$WEBAPP_NAME"
|
||||
service $INSTANCE start
|
||||
else
|
||||
# TODO : affichage des commandes ?
|
||||
true
|
||||
fi
|
||||
done
|
128
oldies/script_inotify-rsync.sh
Executable file
128
oldies/script_inotify-rsync.sh
Executable file
|
@ -0,0 +1,128 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
DIR_SOURCE=""
|
||||
DIR_DESTINATION=""
|
||||
MAX_WAIT=60
|
||||
RSYNC_OPTIONS="-q -aH --delete"
|
||||
INOTIFYWAIT_OPTIONS="-qq -r -e close_write -e attrib -e move -e create -e delete -e unmount"
|
||||
#RSYNC_OPTIONS="-v -aH --delete"
|
||||
#INOTIFYWAIT_OPTIONS="-r -e close_write -e attrib -e move -e create -e delete -e unmount"
|
||||
|
||||
# On essaie de diminuer la priorité de la chose
|
||||
# Aucune importance si les utilitaires ne sont pas dispos
|
||||
renice 15 -p $$ >/dev/null 2>&1
|
||||
ionice -c 3 -p $$ >/dev/null 2>&1
|
||||
|
||||
# Arrêt à la moindre erreur non-catchée
|
||||
set -e
|
||||
|
||||
# Fonctions
|
||||
# Little helper to centralize syslog calls
|
||||
loglog() {
|
||||
LEVEL="$1"
|
||||
shift
|
||||
logger -s -t inotify-rsync -p user.$LEVEL $@
|
||||
}
|
||||
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [-i inotifywait_options] [-r rsync_options] [-t max_wait] -s source_directory -d rsync_destination
|
||||
$0 -h
|
||||
|
||||
-s : specify the rsync source (needs to be a local directory)
|
||||
-d : specify the rsync destination (can be anythin rsync accepts)
|
||||
-i : inotifywait options (minus the -t option)
|
||||
(default : "$INOTIFYWAIT_OPTIONS")
|
||||
-r : rsync options
|
||||
(default : "$RSYNC_OPTIONS")
|
||||
-t : Even without event (or in case of missed event), rsync will be launched every "max_wait" seconds
|
||||
(0 = wait forever) (default: $MAX_WAIT)
|
||||
|
||||
-h : this help screen
|
||||
EOF
|
||||
}
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts s:d:r:w:h o; do
|
||||
case $o in
|
||||
's')
|
||||
DIR_SOURCE="$OPTARG"
|
||||
;;
|
||||
|
||||
'd')
|
||||
DIR_DESTINATION="$OPTARG"
|
||||
;;
|
||||
|
||||
'i')
|
||||
INOTIFYWAIT_OPTIONS="$OPTARG"
|
||||
;;
|
||||
|
||||
'r')
|
||||
RSYNC_OPTIONS="$OPTARG"
|
||||
;;
|
||||
|
||||
'w')
|
||||
MAX_WAIT="$OPTARG"
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
#shift $( expr $OPTIND - 1 )
|
||||
#REPDRUPAL="$1"
|
||||
|
||||
# Some checks
|
||||
if [ -z "$DIR_SOURCE" ] || [ ! -d "$DIR_SOURCE" ]; then
|
||||
loglog err "ERROR: no source specified or directory inexistent." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$DIR_DESTINATION" ]; then
|
||||
loglog err "ERROR: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
# rsync can send error code != 0, we'll have to check
|
||||
# what this code means before failing
|
||||
set +e
|
||||
rsync $RSYNC_OPTIONS "$DIR_SOURCE" "$DIR_DESTINATION"
|
||||
RSYNC_RETURN_CODE="$?"
|
||||
set -e
|
||||
while [ "$RSYNC_RETURN_CODE" -ne "0" ]; do
|
||||
for i in 24; do
|
||||
if [ "$RSYNC_RETURN_CODE" -eq "$i" ]; then
|
||||
# If the return code is "acceptable", we go on
|
||||
loglog debug "DEBUG: rsync returned code '$RSYNC_RETURN_CODE'"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
# The return code wasn't in the "acceptable" list => log + exit
|
||||
loglog err "ERROR: rsync returned unexpected error code : $RSYNC_RETURN_CODE. Script stopped."
|
||||
exit $RSYNC_RETURN_CODE
|
||||
done
|
||||
|
||||
# Wait for another change
|
||||
# inotifywait can send error code != 0, we'll have to check
|
||||
# what this code means before failing
|
||||
set +e
|
||||
inotifywait $INOTIFYWAIT_OPTIONS -t "$MAX_WAIT" "$DIR_SOURCE"
|
||||
INOTIFYWAIT_RETURN_CODE="$?"
|
||||
set -e
|
||||
if [ "$INOTIFYWAIT_RETURN_CODE" -ne "0" ]; then
|
||||
if [ "$INOTIFYWAIT_RETURN_CODE" -ne "2" ]; then
|
||||
loglog err "ERROR: inotifywait returned unexpected error code : $INOTIFYWAIT_RETURN_CODE. Script stopped."
|
||||
exit $INOTIFYWAIT_RETURN_CODE
|
||||
fi
|
||||
fi
|
||||
done
|
138
oldies/script_inotify-rsync_startup-script.sh
Executable file
138
oldies/script_inotify-rsync_startup-script.sh
Executable file
|
@ -0,0 +1,138 @@
|
|||
#! /bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: rsync-inotify
|
||||
# Required-Start: $syslog $local_fs $network
|
||||
# Required-Stop: $syslog $local_fs $network
|
||||
# Should-Start: $named
|
||||
# Should-Stop: $named
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Rsync-inotify launcher
|
||||
# Description: This script launch the rsync-inotify script on the upload
|
||||
# of the XXX instances project.
|
||||
### END INIT INFO
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC="Rsync-Inotify for XXX instances"
|
||||
NAME=inotify-rsync
|
||||
DAEMON=/root/script_inotify-rsync.sh
|
||||
# J'arrive pas à le faire passer correctement à start-stop-daemon :-(
|
||||
#DAEMON_ARGS='-r "-q -aH --delete --password-file=/root/.inotify-rsync-password" -s /srv/XXX/ -d "rsync://XXX-storage-master@srv2.example.net/XXX-storage/"'
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/inotify-rsync.sh
|
||||
|
||||
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
|
||||
# and status_of_proc is working.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
if [ -n "$( pgrep -f "$DAEMON" )" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
start-stop-daemon --start -b --make-pidfile --iosched idle --nicelevel 10 --exec "$DAEMON" --pidfile "$PIDFILE" --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start -b --make-pidfile --iosched idle --nicelevel 10 --exec "$DAEMON" --pidfile "$PIDFILE" -- \
|
||||
-r "-q -aH --delete --password-file=/root/.inotify-rsync-password" -s /srv/XXX/ -d "rsync://storage-master@srv2.example.net/XXX-storage/" \
|
||||
|| return 2
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
|
||||
# Petite vérification supplémentaire :
|
||||
# comme on ne semble pas pouvoir utiliser l'option --exec avec le --stop
|
||||
# de start-stop-daemon, on vérifie que le PID dans PID_FILE correspond bien
|
||||
# notre process
|
||||
PID_CHECK="$( pgrep -f "$DAEMON" )"
|
||||
if [ -z "$PID_CHECK" ] || [ "$PID_CHECK" != "$( cat "$PIDFILE" 2>/dev/null )" ]; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
# start-stop-daemon ne semble pas arrêter proprement le inotifywait qui reste
|
||||
# zombifié jusqu'à son timeout. Du coup, on commence par pkill
|
||||
pkill --signal INT -P "$PID_CHECK" || return 2
|
||||
if [ -n "$( pgrep -f "$DAEMON" )" ]; then
|
||||
start-stop-daemon --stop --quiet --retry=INT/5/KILL/5 --pidfile "$PIDFILE"
|
||||
fi
|
||||
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Many daemons don't delete their pidfiles when they exit.
|
||||
rm -f $PIDFILE
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
restart|force-reload)
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
54
oldies/script_listing-volumetrie-backuppc.sh
Executable file
54
oldies/script_listing-volumetrie-backuppc.sh
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/bin/sh
|
||||
|
||||
BASE_REP="/backuppc/backuppc/pc"
|
||||
|
||||
MAX_NBLIGNES_INCR=30
|
||||
LISTING_FULL=$(printf "%s\n\t%s\t%s\n" "Volumes des dernières sauvegardes complètes :" "Nb fichiers" "Taille" )
|
||||
LISTING_INCR=$(printf "%s\n\t%s\t%s\n" "Volumes des $MAX_NBLIGNES_INCR dernières sauvegardes incrémentales :" "Nb fichiers" "Taille" )
|
||||
|
||||
somme_ligne() {
|
||||
TOTAL_FILES=0
|
||||
TOTAL_SIZE=0
|
||||
|
||||
# note : c'est un peu sale.
|
||||
# Explications : on fait une boucle basée sur un pipe, les variables dans cette boucle
|
||||
# deviennent donc locales à cette boucle.
|
||||
# 'faut que je retrouve comment en sortir proprement
|
||||
cat - | while read line; do
|
||||
echo $(( $TOTAL_FILES + $(printf "%s" "$line" | awk 'BEGIN { FS = "\t" } ; { print $5 }' ) ))
|
||||
TOTAL_FILES=$(( $TOTAL_FILES + $( printf "%s" "$line" | awk 'BEGIN { FS = "\t" } ; { print $5 }' ) ))
|
||||
TOTAL_SIZE=$(( $TOTAL_SIZE + $( printf "%s" "$line" | awk 'BEGIN { FS = "\t" } ; { print $6 }' ) ))
|
||||
printf "%d\t%d\n" "$TOTAL_FILES" "$TOTAL_SIZE"
|
||||
done | tail -n 1
|
||||
}
|
||||
|
||||
cd "$BASE_REP"
|
||||
|
||||
for REP in *; do
|
||||
# On ne prend que les dossiers qui contiennent un fichier non-vide "backups"
|
||||
if [ ! -d "$REP" ]; then
|
||||
continue
|
||||
fi
|
||||
if [ ! -s "$REP/backups" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Listing full
|
||||
LISTING_FULL="$( printf "%s\n%s\t%s" "$LISTING_FULL" "$REP" "$( cat "$REP/backups" | egrep "^[0-9]+[[:space:]]+full" | tail -n 1 | somme_ligne )" )"
|
||||
|
||||
# Listing incrémental
|
||||
#décompte nb sauv.
|
||||
NBLIGNES_INCR="$( cat "$REP/backups" | egrep "^[0-9]+[[:space:]]+incr" | wc -l )"
|
||||
if [ "$NBLIGNES_INCR" -gt $MAX_NBLIGNES_INCR ]; then
|
||||
NBLIGNES_INCR=$MAX_NBLIGNES_INCR
|
||||
fi
|
||||
LISTING_INCR="$( printf "%s\n%s (%dj)\t%s" "$LISTING_INCR" "$REP" "$NBLIGNES_INCR" "$( cat "$REP/backups" | egrep "^[0-9]+[[:space:]]+incr" | tail -n $MAX_NBLIGNES_INCR | somme_ligne )" )"
|
||||
|
||||
|
||||
done
|
||||
|
||||
echo "$LISTING_FULL"
|
||||
echo
|
||||
echo "$LISTING_INCR"
|
||||
|
||||
|
177
oldies/script_ml-gestion-abonne.sh
Executable file
177
oldies/script_ml-gestion-abonne.sh
Executable file
|
@ -0,0 +1,177 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script sert à gérer les abonnements d'une adresse email
|
||||
#
|
||||
# exemple d'utilisation :
|
||||
# - supprimer une adresse de toutes les mailings-list (suppression d'un compte)
|
||||
# - ajouter interactivement une adresse à certaines ML avec un choix par
|
||||
# défaut (salaries, ...)
|
||||
#
|
||||
# note: dans l'autre sens (ie. pour gérer une mailing-list donnée), il vaut
|
||||
# mieux passer par phpldapadmin ou similaire, c'est plus pratique.
|
||||
#
|
||||
# Known bug: ne pas utiliser avec les mailings-lists ou adresses emails
|
||||
# dont le nom contient un espace.
|
||||
|
||||
|
||||
# Inclusion de la conf. + fonctions de base
|
||||
. ./lib_gestion-mailinglists.sh
|
||||
|
||||
# Initialisation des variables "globales"
|
||||
MODE_INTERACTIF="0"
|
||||
MODE_LISTING="0"
|
||||
AJOUTS=""
|
||||
SUPPRESSIONS=""
|
||||
LOGFILE=$( mktemp )
|
||||
LISTING_MAILING_LISTS=$( afficher_listing_mailinglists )
|
||||
|
||||
|
||||
|
||||
# Fonctions
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [-i] [-r liste] [-r ALL] [-a liste] [-a ...] mail
|
||||
$0 -h
|
||||
|
||||
-i : mode interactif.
|
||||
-a liste : ajoute le mail à la liste. En mode interactif, propose par défaut cette liste au prompt.
|
||||
-r liste : supprime le mail de la liste. ALL = suppression de toutes les listes. En mode interactif, supprime les listes de la proposition.
|
||||
-l : liste les mailings-lists dans lesquelles le mail apparaît.
|
||||
|
||||
Note: les ajouts prennent le pas sur les suppressions.
|
||||
EOF
|
||||
}
|
||||
|
||||
terminaison() {
|
||||
if [ "$1" = "" ] || [ "$1" -eq 0 ]; then
|
||||
rm -f "$LOGFILE"
|
||||
RETOUR=0
|
||||
else
|
||||
if [ -s "$LOGFILE" ]; then
|
||||
printf "NOTICE: log dispo : %s\n" "$LOGFILE" >&2
|
||||
else
|
||||
rm -f "$LOGFILE"
|
||||
fi
|
||||
RETOUR="$1"
|
||||
fi
|
||||
exit "$RETOUR"
|
||||
}
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts a:r:ihl f; do
|
||||
case $f in
|
||||
'a')
|
||||
AJOUTS=$( echo $AJOUTS $OPTARG )
|
||||
;;
|
||||
|
||||
'r')
|
||||
SUPPRESSIONS=$( echo $SUPPRESSIONS $OPTARG )
|
||||
;;
|
||||
|
||||
'i')
|
||||
MODE_INTERACTIF=1
|
||||
;;
|
||||
|
||||
'l')
|
||||
MODE_LISTING=1
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
terminaison 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
terminaison 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
MAIL="$1"
|
||||
|
||||
# Petite vérif.
|
||||
if [ "$MAIL" = "" ]; then
|
||||
echo "ERREUR: aucune adresse email fournie." >&2
|
||||
usage
|
||||
terminaison 1
|
||||
fi
|
||||
|
||||
# Mode listing
|
||||
if [ "$MODE_LISTING" -gt 0 ]; then
|
||||
afficher_abonnements_en_cours "$MAIL"
|
||||
terminaison 0
|
||||
fi
|
||||
|
||||
# Les mailings-lists demandées existent-elles ?
|
||||
TMP=0
|
||||
for ML in $AJOUTS $SUPPRESSIONS; do
|
||||
if [ $( printf "%s\nALL\n" "$LISTING_MAILING_LISTS" | egrep -c "^$ML$" ) -ne 1 ]; then
|
||||
echo "ERREUR: la mailing-list ne semble pas exister : $ML" >&2
|
||||
TMP=1
|
||||
fi
|
||||
done
|
||||
test "$TMP" -eq 0 || terminaison 1
|
||||
|
||||
# Construction de la liste finale des abonnements
|
||||
if [ $( echo "$SUPPRESSIONS" | grep -wc "ALL" ) -gt 0 ]; then
|
||||
# Suppression de tous les abonnements (paramètre "-r ALL")
|
||||
SUPPRESSIONS=$( afficher_abonnements_en_cours "$MAIL" )
|
||||
fi
|
||||
LISTE_FINALE=$( (afficher_abonnements_en_cours "$MAIL" | grep -wFv "$( echo "$SUPPRESSIONS" | sed 's/ \+/\n/g' )" ; echo "$AJOUTS" | sed 's/ \+/\n/g') | grep -v "^$" | sort -u )
|
||||
|
||||
# Entrée dans le "mode interactif"
|
||||
BOUCLE_INTERACTIVE=$MODE_INTERACTIF # simple copie cosmétique, histoire de garder le paramètre jusqu'au bout (sait-on jamais :)
|
||||
while [ "$BOUCLE_INTERACTIVE" -eq 1 ]; do
|
||||
# Listing des mailing-lists disponibles
|
||||
echo "Listing des mailing-lists : "
|
||||
printf "%s\n" "$LISTING_MAILING_LISTS" | sed 's/^/ /'
|
||||
|
||||
# Prompt pour la modification du listing
|
||||
LISTE_FINALE=$( echo $LISTE_FINALE ) # ça permet de convertir facilement en une liste mono-ligne :)
|
||||
printf "Indiquer les listes auxquelles l'email %s doit être abonné, ligne vide pour terminer\n(. pour ignorer la proposition et annuler les entrées précédentes)\n[%s]\n" "$MAIL" "$LISTE_FINALE"
|
||||
LISTE_USER=$( while read LINE; do if [ "$LINE" = "" ]; then exit 0; else echo "$LINE"; fi; done )
|
||||
|
||||
# écrasement de LISTE_FINALE si l'utilisateur a entré qqchose
|
||||
if [ "$LISTE_USER" != "" ]; then
|
||||
LISTE_FINALE=""
|
||||
fi
|
||||
|
||||
# On vérifie chaque entrée (un peu redondant avec la boucle de vérif. précédente)
|
||||
BOUCLE_INTERACTIVE=0
|
||||
for ML in $LISTE_USER; do
|
||||
# Si c'est un "." qui a été rentré, on efface la liste finale
|
||||
if [ "$ML" = "." ]; then
|
||||
LISTE_FINALE=""
|
||||
|
||||
# sinon, on vérifie simplement que la mailing-list existe
|
||||
elif [ $( printf "%s\n" "$LISTING_MAILING_LISTS" | egrep -c "^$ML$" ) -ne 1 ]; then
|
||||
# Si elle n'existe pas: nouveau tour gratuit
|
||||
echo "ERREUR: la mailing-list ne semble pas exister : $ML" >&2
|
||||
BOUCLE_INTERACTIVE=1
|
||||
else
|
||||
# On concatène (astuce avec echo pour enlever les espaces inutiles)
|
||||
LISTE_FINALE=$( echo $LISTE_FINALE $ML )
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
# - les suppressions
|
||||
for ML in $( afficher_abonnements_en_cours "$MAIL" | grep -wFv "$( echo "$LISTE_FINALE" | sed 's/ \+/\n/g' )" ); do
|
||||
printf "Suppression de %s de la mailing-list %s.\n" "$MAIL" "$ML"
|
||||
supprimer_abonnement "$MAIL" "$ML" >"$LOGFILE" 2>&1 || terminaison 1
|
||||
done
|
||||
|
||||
# - les créations d'abonnement
|
||||
for ML in $( echo "$LISTE_FINALE" | sed 's/ \+/\n/g' | grep -wFv "$( afficher_abonnements_en_cours "$MAIL" )" ); do
|
||||
printf "Ajout de %s à la mailing-list %s.\n" "$MAIL" "$ML"
|
||||
creer_abonnement "$MAIL" "$ML" >"$LOGFILE" 2>&1 || terminaison 1
|
||||
done
|
||||
|
||||
|
||||
# Fin du script - nettoyage
|
||||
terminaison 0
|
||||
|
214
oldies/script_ml-gestion-mailinglist.sh
Executable file
214
oldies/script_ml-gestion-mailinglist.sh
Executable file
|
@ -0,0 +1,214 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script sert à créer/supprimer une mailing-list
|
||||
#
|
||||
# exemple d'utilisation :
|
||||
# - créer une mailing-list et lui ajouter des abonnés,
|
||||
# - retirer des abonnés d'une mailing-list,
|
||||
# - supprimer une mailing-list
|
||||
#
|
||||
# note: dans l'autre sens (ie. gérer les abonnements d'une adresse donnée),
|
||||
# il existe le script_ml-gestion-abonne.sh
|
||||
#
|
||||
# Known bug: ne pas utiliser avec les mailings-lists ou adresses emails
|
||||
# dont le nom contient un espace.
|
||||
|
||||
|
||||
# Inclusion de la conf. + fonctions de base
|
||||
. ./lib_gestion-mailinglists.sh
|
||||
|
||||
# Initialisation des variables "globales"
|
||||
MODE_INTERACTIF="0"
|
||||
MODE_LISTING_ABONNES="0"
|
||||
CREATION_SUPPRESSION="0" # 0: neutre, -1: suppression, 1: creation
|
||||
AJOUTS=""
|
||||
SUPPRESSIONS=""
|
||||
LOGFILE=$( mktemp )
|
||||
|
||||
|
||||
|
||||
# Fonctions
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [-i] [ -c | -d ] [-r email] [-r ALL] [-a email] [-a ...] mail
|
||||
$0 -L
|
||||
$0 -h
|
||||
|
||||
-i : mode interactif.
|
||||
-c : crée la mailing-list.
|
||||
-d : supprime la mailing-list.
|
||||
-a mail : ajoute le mail à la liste. En mode interactif, propose par défaut cet
|
||||
email au prompt.
|
||||
-r mail : supprime le mail de la liste. ALL = suppression de tous les abonnés.
|
||||
En mode interactif, supprime les listes de la proposition.
|
||||
-l : liste les abonnés de la mailing-list.
|
||||
-L : liste les mailing-list
|
||||
|
||||
Note: les ajouts prennent le pas sur les suppressions.
|
||||
EOF
|
||||
}
|
||||
|
||||
terminaison() {
|
||||
if [ "$1" = "" ] || [ "$1" -eq 0 ]; then
|
||||
rm -f "$LOGFILE"
|
||||
RETOUR=0
|
||||
else
|
||||
if [ -s "$LOGFILE" ]; then
|
||||
printf "NOTICE: log dispo : %s\n" "$LOGFILE" >&2
|
||||
else
|
||||
rm -f "$LOGFILE"
|
||||
fi
|
||||
RETOUR="$1"
|
||||
fi
|
||||
exit "$RETOUR"
|
||||
}
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts cda:r:ihlL f; do
|
||||
case $f in
|
||||
'c')
|
||||
CREATION_SUPPRESSION=1
|
||||
;;
|
||||
|
||||
'd')
|
||||
CREATION_SUPPRESSION=-1
|
||||
;;
|
||||
|
||||
'a')
|
||||
AJOUTS=$( echo $AJOUTS $OPTARG )
|
||||
;;
|
||||
|
||||
'r')
|
||||
SUPPRESSIONS=$( echo $SUPPRESSIONS $OPTARG )
|
||||
;;
|
||||
|
||||
'i')
|
||||
MODE_INTERACTIF=1
|
||||
;;
|
||||
|
||||
'l')
|
||||
MODE_LISTING_ABONNES=1
|
||||
;;
|
||||
|
||||
'L')
|
||||
afficher_listing_mailinglists
|
||||
terminaison 0
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
terminaison 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
terminaison 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
MAILINGLIST="$1"
|
||||
|
||||
# Petite vérif.
|
||||
if [ "$MAILINGLIST" = "" ]; then
|
||||
echo "ERREUR: aucune mailing-list n'a été indiquée." >&2
|
||||
usage
|
||||
terminaison 1
|
||||
fi
|
||||
|
||||
# Mode listing des abonnes d'une mailing-linst
|
||||
if [ "$MODE_LISTING_ABONNES" -gt 0 ]; then
|
||||
# On vérifie quand même que la mailing-list existe...
|
||||
if [ $( afficher_listing_mailinglists | grep -wc "^$MAILINGLIST$" ) -ne 1 ]; then
|
||||
echo "ERREUR: mailing-list inexistante." >&2
|
||||
terminaison 1
|
||||
fi
|
||||
|
||||
# Listing des abonnés de la mailing-list
|
||||
afficher_abonnes_mailinglist "$MAILINGLIST"
|
||||
terminaison 0
|
||||
fi
|
||||
|
||||
# La mailing-list demandée existe-elle ?
|
||||
if [ $( printf "%s\n" "$( afficher_listing_mailinglists )" | egrep -c "^$MAILINGLIST$" ) -ne 1 ]; then
|
||||
# Si elle n'existe pas, doit-on la créer ?
|
||||
if [ $CREATION_SUPPRESSION -lt 1 ]; then
|
||||
echo "ERREUR: la mailing-list ne semble pas exister : $MAILINGLIST" >&2
|
||||
terminaison 1
|
||||
else
|
||||
# On crée la mailing-list
|
||||
printf "Création de la mailing-list..."
|
||||
if creer_mailinglist "$MAILINGLIST" >"$LOGFILE" 2>&1; then
|
||||
printf " [OK]\n"
|
||||
else
|
||||
printf "\nProblèmes à la création de la mailing-list. Cf log.\n" >&2
|
||||
terminaison 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Si elle existe, doit-on la supprimer ?
|
||||
if [ "$CREATION_SUPPRESSION" -lt 0 ]; then
|
||||
# On la supprime et on arrête là le script
|
||||
printf "Suppression de la mailing-list..."
|
||||
if supprimer_mailinglist "$MAILINGLIST" >"$LOGFILE" 2>&1; then
|
||||
printf "[OK]\n";
|
||||
terminaison 0
|
||||
else
|
||||
printf "\nProblèmes à la suppression de la mailing-list. Cf log.\n" >&2
|
||||
terminaison 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Construction de la liste finale des abonnements
|
||||
if [ $( echo "$SUPPRESSIONS" | grep -wc "ALL" ) -gt 0 ]; then
|
||||
# Suppression de tous les abonnés (paramètre "-r ALL")
|
||||
SUPPRESSIONS=$( afficher_abonnes_mailinglist "$MAILINGLIST" )
|
||||
fi
|
||||
LISTE_FINALE=$( (afficher_abonnes_mailinglist "$MAILINGLIST" | grep -wFv "$( echo "$SUPPRESSIONS" | sed 's/ \+/\n/g' )" ; echo "$AJOUTS" | sed 's/ \+/\n/g') | grep -v "^$" | sort -u )
|
||||
|
||||
# Entrée dans le "mode interactif"
|
||||
BOUCLE_INTERACTIVE=$MODE_INTERACTIF # simple copie cosmétique, histoire de garder le paramètre jusqu'au bout (sait-on jamais :)
|
||||
while [ "$BOUCLE_INTERACTIVE" -eq 1 ]; do
|
||||
# Prompt pour la modification du listing
|
||||
LISTE_FINALE=$( echo $LISTE_FINALE ) # ça permet de convertir facilement en une liste mono-ligne :)
|
||||
printf "Indiquer les emails qui seront abonnés à la liste '%s', ligne vide pour terminer\n(. pour ignorer la proposition et annuler les entrées précédentes)\n[%s]\n" "$MAILINGLIST" "$LISTE_FINALE"
|
||||
LISTE_USER=$( while read LINE; do if [ "$LINE" = "" ]; then exit 0; else echo "$LINE"; fi; done )
|
||||
|
||||
# écrasement de LISTE_FINALE si l'utilisateur a entré qqchose
|
||||
if [ "$LISTE_USER" != "" ]; then
|
||||
LISTE_FINALE=""
|
||||
fi
|
||||
|
||||
# On vérifie chaque entrée (un peu redondant avec la boucle de vérif. précédente)
|
||||
BOUCLE_INTERACTIVE=0
|
||||
for MAIL in $LISTE_USER; do
|
||||
# Si c'est un "." qui a été rentré, on efface la liste finale
|
||||
if [ "$MAIL" = "." ]; then
|
||||
LISTE_FINALE=""
|
||||
else
|
||||
# sinon, on concatène (astuce avec echo pour enlever les espaces inutiles)
|
||||
LISTE_FINALE=$( echo $LISTE_FINALE $MAIL )
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
# - les suppressions
|
||||
for MAIL in $( afficher_abonnes_mailinglist "$MAILINGLIST" | grep -wFv "$( echo "$LISTE_FINALE" | sed 's/ \+/\n/g' )" ); do
|
||||
printf "Suppression de %s de la mailing-list %s.\n" "$MAIL" "$MAILINGLIST"
|
||||
supprimer_abonnement "$MAIL" "$MAILINGLIST" >"$LOGFILE" 2>&1 || terminaison 1
|
||||
done
|
||||
|
||||
# - les créations d'abonnement
|
||||
for MAIL in $( echo "$LISTE_FINALE" | sed 's/ \+/\n/g' | grep -wFv "$( afficher_abonnes_mailinglist "$MAILINGLIST" )" ); do
|
||||
printf "Ajout de %s à la mailing-list %s.\n" "$MAIL" "$MAILINGLIST"
|
||||
creer_abonnement "$MAIL" "$MAILINGLIST" >"$LOGFILE" 2>&1 || terminaison 1
|
||||
done
|
||||
|
||||
|
||||
# Fin du script - nettoyage
|
||||
terminaison 0
|
||||
|
591
oldies/script_multi-instance-postgresql.sh
Executable file
591
oldies/script_multi-instance-postgresql.sh
Executable file
|
@ -0,0 +1,591 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script sert à créer ou détruire :
|
||||
# - une instance PostgreSQL (PGDATA).
|
||||
|
||||
# Il peut également gérer un serveur esclave en définissant la
|
||||
# variable $ESCLAVE . Dans ce cas là, mieux vaut avoir une authentification
|
||||
# par clef (les opérations se font par ssh)
|
||||
#
|
||||
# Attention, ce script affiche les identifiants à l'écran.
|
||||
|
||||
# Prérequis :
|
||||
# - PostgreSQL
|
||||
# Si utilisation d'un esclave :
|
||||
# - une authentification pour l'utilisateur root local vers root@$ESCLAVE par clef,
|
||||
# - une authentification pour l'utilisateur postgres local vers postgres@$ESCLAVE par clef.
|
||||
|
||||
# Trucs à nettoyer (si quelque chose part en vrille, ou simplement
|
||||
# pour désinstaller ):
|
||||
# - TODO
|
||||
|
||||
# Version de PostgreSQL : 9.1 seule testée
|
||||
VERSION_POSTGRESQL="9.1"
|
||||
# Mettre ci-dessous le nom d'hôte ou l'IP du serveur esclave
|
||||
# (utilisé par la config PG + les connexions SSH pour l'exécution
|
||||
# des commandes distantes de ce script)
|
||||
ESCLAVE=""
|
||||
# idem pour le maître (vu depuis l'esclave en cas de réseau privé)
|
||||
# (utilisé pour la config PG)
|
||||
MAITRE=""
|
||||
|
||||
# Initialisation des variables globales
|
||||
MODE_CREATION=0
|
||||
MODE_DESTRUCTION=0
|
||||
POSTGRESQL_REPLICATION_USER_NAME="repliquser"
|
||||
POSTGRESQL_LOCALE="fr_FR.utf8"
|
||||
POSTGRESQL_PORT=""
|
||||
|
||||
# Par défaut, on arrête le script à la première erreur non "catchée"
|
||||
set -e
|
||||
|
||||
# On s'exécute dans un dossier accessible à l'utilisateur postgres
|
||||
cd /tmp
|
||||
|
||||
# Fonctions
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 -c cluster-name [ -e <hostname de l'esclave> -m <hostname du maître> ] [ -p <numéro de port> ]
|
||||
$0 -d cluster-name [ -e <hostname de l'esclave> -m <hostname du maître> ]
|
||||
$0 -h
|
||||
|
||||
-c xxx : création d'une instance/cluster nommée 'xxx'
|
||||
-d xxx : destruction de l'instance nommée 'xxx'
|
||||
|
||||
-p nnn : numéro de port à affecter au nouveau cluster (par défaut, 'auto')
|
||||
|
||||
# Ce script peut générer la configuration nécessaire au streaming replication
|
||||
-e esclave : nom d'hôte ou IP de l'esclave
|
||||
-m maitre : nom d'hôte ou IP du serveur maître
|
||||
|
||||
-h : ce message d'aide
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1 : IPv4, IPv6 ou nom d'hôte
|
||||
# Cette fonction suffixe d'un /32 ou /128
|
||||
# la chaîne si celle-ci est une adresse IP
|
||||
add_mask_ip() {
|
||||
test -n "$1" || exit 1
|
||||
|
||||
if [ $( echo "$1" | egrep -c "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$" ) -gt 0 ]; then
|
||||
printf "$1/32"
|
||||
elif [ $( echo "$1" | egrep -c "^[[:xdigit:]:]*$" ) -gt 0 ]; then
|
||||
printf "$1/128"
|
||||
else
|
||||
printf "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1 : IP esclave
|
||||
# $2 : version PostgreSQL
|
||||
# $3 : nom de l'instance
|
||||
generate_patch_postgresqlconf_master() {
|
||||
test -n "$1" && test -n "$2" && test -n "$3" || exit 1
|
||||
cat <<EOF
|
||||
@@ -56,6 +56,8 @@
|
||||
|
||||
# - Connection Settings -
|
||||
|
||||
+# Script MI PostgreSQL : écoute sur toutes les interfaces nécessaire pour la streaming replication
|
||||
+listen_addresses = '*'
|
||||
#listen_addresses = 'localhost' # what IP address(es) to listen on;
|
||||
# comma-separated list of addresses;
|
||||
# defaults to 'localhost', '*' = all
|
||||
@@ -150,6 +152,8 @@ shared_buffers = 24MB # min 128kB
|
||||
|
||||
# - Settings -
|
||||
|
||||
+# Script MI PostgreSQL : serveur maître
|
||||
+wal_level = hot_standby
|
||||
#wal_level = minimal # minimal, archive, or hot_standby
|
||||
# (change requires restart)
|
||||
#fsync = on # turns forced synchronization on or off
|
||||
@@ -178,9 +182,10 @@ shared_buffers = 24MB # min 128kB
|
||||
|
||||
# - Archiving -
|
||||
|
||||
-#archive_mode = off # allows archiving to be done
|
||||
+# Script MI PostgreSQL : Serveur maître: activation de l'archivage et de l'envoi vers l'esclave
|
||||
+archive_mode = on # allows archiving to be done
|
||||
# (change requires restart)
|
||||
-#archive_command = '' # command to use to archive a logfile segment
|
||||
+archive_command = 'scp -q -B -C %p postgres@$1:/var/lib/postgresql/$2/$3/archives_from_master/%f' # command to use to archive a logfile segment
|
||||
#archive_timeout = 0 # force a logfile segment switch after this
|
||||
# number of seconds; 0 disables
|
||||
|
||||
@@ -193,10 +198,12 @@
|
||||
|
||||
# These settings are ignored on a standby server
|
||||
|
||||
+max_wal_senders = 3
|
||||
#max_wal_senders = 0 # max number of walsender processes
|
||||
# (change requires restart)
|
||||
#wal_sender_delay = 1s # walsender cycle time, 1-10000 milliseconds
|
||||
-#wal_keep_segments = 0 # in logfile segments, 16MB each; 0 disables
|
||||
+# Script MI PostgreSQL : serveur maître: conservation des WAL
|
||||
+wal_keep_segments = 32 # in logfile segments, 16MB each; 0 disables
|
||||
#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed
|
||||
#replication_timeout = 60s # in milliseconds; 0 disables
|
||||
#synchronous_standby_names = '' # standby servers that provide sync rep
|
||||
@@ -207,6 +213,9 @@ shared_buffers = 24MB # min 128kB
|
||||
|
||||
# These settings are ignored on a master server
|
||||
|
||||
+# Script MI PostgreSQL : mis en place sur le maître comme sur l'esclave, pour homogénéiser
|
||||
+# comme il est ignoré sur le maître, ça ne pose pas de souci :)
|
||||
+hot_standby = on
|
||||
#hot_standby = off # "on" allows queries during recovery
|
||||
# (change requires restart)
|
||||
#max_standby_archive_delay = 30s # max delay before canceling queries
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1 : nom de l'instance
|
||||
generate_patch_postgresql_pghbaconf() {
|
||||
test -n "$1" || exit 1
|
||||
cat <<EOF
|
||||
@@ -87,11 +87,11 @@ local all postgres peer
|
||||
# TYPE DATABASE USER ADDRESS METHOD
|
||||
|
||||
# "local" is for Unix domain socket connections only
|
||||
-local all all peer
|
||||
+local $1 $1 md5
|
||||
# IPv4 local connections:
|
||||
-host all all 127.0.0.1/32 md5
|
||||
+host $1 $1 127.0.0.1/32 md5
|
||||
# IPv6 local connections:
|
||||
-host all all ::1/128 md5
|
||||
+host $1 $1 ::1/128 md5
|
||||
# Allow replication connections from localhost, by a user with the
|
||||
# replication privilege.
|
||||
#local replication postgres peer
|
||||
EOF
|
||||
}
|
||||
|
||||
# Pas d'arguments
|
||||
generate_patch_postgresqlconf_slave() {
|
||||
cat <<EOF
|
||||
@@ -56,6 +56,8 @@
|
||||
|
||||
# - Connection Settings -
|
||||
|
||||
+# Script MI PostgreSQL : écoute sur toutes les interfaces nécessaire pour la streaming replication
|
||||
+listen_addresses = '*'
|
||||
#listen_addresses = 'localhost' # what IP address(es) to listen on;
|
||||
# comma-separated list of addresses;
|
||||
# defaults to 'localhost', '*' = all
|
||||
@@ -150,6 +152,8 @@ shared_buffers = 24MB # min 128kB
|
||||
|
||||
# - Settings -
|
||||
|
||||
+# Script MI PostgreSQL : serveur esclave
|
||||
+wal_level = hot_standby
|
||||
#wal_level = minimal # minimal, archive, or hot_standby
|
||||
# (change requires restart)
|
||||
#fsync = on # turns forced synchronization on or off
|
||||
@@ -193,10 +198,12 @@
|
||||
|
||||
# These settings are ignored on a standby server
|
||||
|
||||
+max_wal_senders = 3
|
||||
#max_wal_senders = 0 # max number of walsender processes
|
||||
# (change requires restart)
|
||||
#wal_sender_delay = 1s # walsender cycle time, 1-10000 milliseconds
|
||||
-#wal_keep_segments = 0 # in logfile segments, 16MB each; 0 disables
|
||||
+# Script MI PostgreSQL : serveur maître: conservation des WAL
|
||||
+wal_keep_segments = 32 # in logfile segments, 16MB each; 0 disables
|
||||
#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed
|
||||
#replication_timeout = 60s # in milliseconds; 0 disables
|
||||
#synchronous_standby_names = '' # standby servers that provide sync rep
|
||||
@@ -207,6 +213,9 @@ shared_buffers = 24MB # min 128kB
|
||||
|
||||
# These settings are ignored on a master server
|
||||
|
||||
+# Script MI PostgreSQL : mis en place sur le maître comme sur l'esclave, pour homogénéiser
|
||||
+# comme il est ignoré sur le maître, ça ne pose pas de souci :)
|
||||
+hot_standby = on
|
||||
#hot_standby = off # "on" allows queries during recovery
|
||||
# (change requires restart)
|
||||
#max_standby_archive_delay = 30s # max delay before canceling queries
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments:
|
||||
# $1 : IP maître
|
||||
# $2 : port maître (idem esclave, en fait)
|
||||
# $3 : utilisateur dédié à la réplication
|
||||
# $4 : mot de passe dudit utilisateur
|
||||
# $5 : version de PostgreSQL
|
||||
# $6 : nom de l'instance
|
||||
# $7 : chemin complet de pg_archivecleanup (si vide, désactivé)
|
||||
generate_file_postgresqlrecoveryconf_slave() {
|
||||
local ARCHIVE_CLEANUP_COMMAND
|
||||
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" && test -n "$5" && test -n "$6" || exit 1
|
||||
|
||||
if ! test -n "$7"; then
|
||||
ARCHIVE_CLEANUP_COMMAND="#archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/$5/$6/archives_from_master %r'"
|
||||
else
|
||||
ARCHIVE_CLEANUP_COMMAND="archive_cleanup_command = '$7 /var/lib/postgresql/$5/$6/archives_from_master %r'"
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
# Note that recovery.conf must be in \$PGDATA directory.
|
||||
|
||||
# Specifies whether to start the server as a standby. In streaming replication,
|
||||
# this parameter must be set to on.
|
||||
standby_mode = 'on'
|
||||
|
||||
# Specifies a connection string which is used for the standby server to connect
|
||||
# with the primary.
|
||||
primary_conninfo = 'host=$1 port=$2 user=$3 password=$4'
|
||||
|
||||
# Specifies a trigger file whose presence should cause streaming replication to
|
||||
# end (i.e., failover).
|
||||
# Cf pg_ctlcluster promote pour une alternative
|
||||
trigger_file = '/var/lib/postgresql/trigger-postgresql'
|
||||
|
||||
# Specifies a command to load archive segments from the WAL archive. If
|
||||
# wal_keep_segments is a high enough number to retain the WAL segments
|
||||
# required for the standby server, this may not be necessary. But
|
||||
# a large workload can cause segments to be recycled before the standby
|
||||
# is fully synchronized, requiring you to start again from a new base backup.
|
||||
restore_command = 'cp /var/lib/postgresql/$5/$6/archives_from_master/%f "%p"'
|
||||
|
||||
# Specifies a command to clean up obsolete archive logs
|
||||
$ARCHIVE_CLEANUP_COMMAND
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments:
|
||||
# $1 : Nom de la bdd / de l'utilisateur
|
||||
# $2 : mot de passe de l'utilisateur
|
||||
generate_script_postgresql_creation_db_et_user() {
|
||||
local NOM_INSTANCE POSTGRESQL_PASSWORD
|
||||
test -n "$1" && test -n "$2" || exit 1
|
||||
NOM_INSTANCE="$1"
|
||||
POSTGRESQL_PASSWORD="$2"
|
||||
|
||||
cat <<EOF
|
||||
-- Création de l'utilisateur principal
|
||||
CREATE USER "$NOM_INSTANCE" WITH PASSWORD '$POSTGRESQL_PASSWORD' CONNECTION LIMIT 50;
|
||||
|
||||
|
||||
-- Restriction des privilèges par défaut
|
||||
-- Cette partie du script vient en grande partie de :
|
||||
-- http://wiki.postgresql.org/wiki/Shared_Database_Hosting
|
||||
|
||||
-- Connexion à template1
|
||||
\c template1
|
||||
-- Révocation sur la base template1
|
||||
REVOKE ALL ON DATABASE template1 FROM public;
|
||||
REVOKE ALL ON SCHEMA public FROM public;
|
||||
GRANT ALL ON SCHEMA public TO postgres;
|
||||
|
||||
-- Ce passage-là est plus parano, mais à étudier avant suppression
|
||||
REVOKE ALL ON pg_user FROM public;
|
||||
REVOKE ALL ON pg_roles FROM public;
|
||||
REVOKE ALL ON pg_group FROM public;
|
||||
REVOKE ALL ON pg_authid FROM public;
|
||||
REVOKE ALL ON pg_auth_members FROM public;
|
||||
REVOKE ALL ON pg_database FROM public;
|
||||
REVOKE ALL ON pg_tablespace FROM public;
|
||||
REVOKE ALL ON pg_settings FROM public;
|
||||
|
||||
|
||||
-- Création de la nouvelle base de données
|
||||
CREATE DATABASE "$NOM_INSTANCE" WITH OWNER = "$NOM_INSTANCE" ENCODING = 'UTF8';
|
||||
REVOKE ALL ON DATABASE "$NOM_INSTANCE" FROM public;
|
||||
\c $NOM_INSTANCE
|
||||
REVOKE ALL ON SCHEMA public FROM public;
|
||||
GRANT ALL ON SCHEMA public TO "$NOM_INSTANCE";
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments:
|
||||
# $1 : nom de l'utilisateur dédié à la réplication
|
||||
# $2 : mot de passe dudit utilisateur
|
||||
generate_script_postgresql_creation_replication_user() {
|
||||
test -n "$1" && test -n "$2" || exit 1
|
||||
POSTGRESQL_REPLICATION_USER_NAME="$1"
|
||||
POSTGRESQL_REPLICATION_PASSWORD="$2"
|
||||
|
||||
cat <<EOF
|
||||
-- Création de l'utilisateur utilisé par l'esclave pour la streaming replication
|
||||
CREATE USER $POSTGRESQL_REPLICATION_USER_NAME WITH PASSWORD '$POSTGRESQL_REPLICATION_PASSWORD' REPLICATION;
|
||||
EOF
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# none
|
||||
log_alias() {
|
||||
# Cette fonction est utilisée pour "capturer" les sorties des différentes
|
||||
# commandes (hors messages générés par le script lui-même)
|
||||
# Note : elle peut être modifiée pour envoyer les messages vers un fichier
|
||||
# de log temporaire. Ça serait plus propre.
|
||||
sed 's/^/ /'
|
||||
}
|
||||
fancylog() {
|
||||
BEGINNING="$( printf "%s" "$1" | head -n 1 | sed -n "s/^\([A-Z]\+\):.*/\1/p" )"
|
||||
if [ -n "$BEGINNING" ] && [ -t 1 ] && tput setaf 1 >/dev/null 2>&1; then
|
||||
case "$BEGINNING" in
|
||||
"ERREUR"|"ERROR")
|
||||
tput setaf 1;;
|
||||
"WARN"|"WARNING")
|
||||
tput setaf 3;;
|
||||
"INFO"|"DEBUG")
|
||||
tput setaf 2;;
|
||||
esac
|
||||
printf "%s" "$BEGINNING"
|
||||
tput op
|
||||
printf "%s\n" "$( printf "%s" "$1" | sed '1 s/^[A-Z]\+:/:/' )"
|
||||
else
|
||||
printf "%s\n" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts c:d:e:m:p:h f; do
|
||||
case $f in
|
||||
'c')
|
||||
MODE_CREATION=1
|
||||
NOM_INSTANCE="$OPTARG"
|
||||
;;
|
||||
|
||||
'd')
|
||||
MODE_DESTRUCTION=1
|
||||
NOM_INSTANCE="$OPTARG"
|
||||
;;
|
||||
|
||||
'e')
|
||||
ESCLAVE="$OPTARG"
|
||||
;;
|
||||
|
||||
'm')
|
||||
MAITRE="$OPTARG"
|
||||
;;
|
||||
|
||||
'p')
|
||||
if [ "$OPTARG" = "auto" ]; then
|
||||
unset POSTGRESQL_PORT
|
||||
else
|
||||
POSTGRESQL_PORT="$( printf "%d" "$OPTARG" )"
|
||||
fi
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
#(code inutile, mais que je garde parce qu'on ne sait jamais)
|
||||
#shift $( expr $OPTIND - 1 )
|
||||
#DATA="$1"
|
||||
if [ -n "$MAITRE" ] && [ -n "$ESCLAVE" ]; then
|
||||
MAITRE_WITH_MASK=$( add_mask_ip "$MAITRE" )
|
||||
ESCLAVE_WITH_MASK=$( add_mask_ip "$ESCLAVE" )
|
||||
fi
|
||||
|
||||
# Petite vérif.
|
||||
case $(( $MODE_CREATION + $MODE_DESTRUCTION )) in
|
||||
'0')
|
||||
fancylog "ERREUR: veuillez choisir entre création et destruction." >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
'2')
|
||||
fancylog "ERREUR: tu veux créer et détruire en même temps, petit malin ?" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Petites vérifications préliminaires :
|
||||
fancylog "INFO: petites vérifications préliminaires..."
|
||||
# - vérifications sur le nom du clustername fourni
|
||||
OLD_LC_ALL="$LC_ALL"
|
||||
export LC_ALL=C
|
||||
export LANG=C
|
||||
if [ $( printf "$NOM_INSTANCE" | egrep -c "^[a-z][a-z0-9_]{0,14}$" ) -ne 1 ]; then
|
||||
fancylog "ERREUR: clustername vide ou contenant des caractères interdits : regexp : [a-z][a-z0-9_]{0,14}" >&2
|
||||
exit 1
|
||||
fi
|
||||
export LC_ALL="$OLD_LC_ALL"
|
||||
export LANG="$OLD_LC_ALL"
|
||||
# - est-ce que l'auth. SSH par clef fonctionne pour root et postgres ?
|
||||
if [ -n "$ESCLAVE" ]; then
|
||||
# - vérification de l'auth. par clefs SSH
|
||||
if ! ssh -o BatchMode=yes root@$ESCLAVE /bin/true; then
|
||||
fancylog "ERREUR: auth. par clef SSH non configurée pour l'utilisateur 'root'."
|
||||
exit 1
|
||||
fi
|
||||
if ! su -c "ssh -o BatchMode=yes postgres@$ESCLAVE /bin/true" postgres; then
|
||||
fancylog "ERREUR: auth. par clef SSH non configurée pour l'utilisateur 'postgres'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# - vérification de la présence de $MAITRE
|
||||
if [ ! -n "$MAITRE" ]; then
|
||||
fancylog "ERREUR: serveur esclave indiqué, mais pas de serveur maître (option -m)." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# - est-ce qu'on est bien sur une Debian 6 ou 7
|
||||
# (c'est surtout pour éviter les mauvaises surprises, ce script n'ayant pas été testé ailleurs)
|
||||
if [ ! -f "/etc/debian_version" ] || [ $( egrep -c "^(6.|7.)" /etc/debian_version ) -ne 1 ]; then
|
||||
fancylog "ERREUR: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$ESCLAVE" ] && [ "$( ssh root@$ESCLAVE 'egrep -c "^(6.|7.)" /etc/debian_version' )" -ne 1 ]; then
|
||||
fancylog "ERREUR: ESCLAVE: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# - est-ce que la version attendue de PostgreSQL est bien installée ?
|
||||
if ! dpkg -s "postgresql-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
|
||||
fancylog "ERREUR: PostgreSQL $VERSION_POSTGRESQL ne semble pas installée." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$ESCLAVE" ] && ! ssh root@$ESCLAVE dpkg -s "postgresql-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
|
||||
fancylog "ERREUR: PostgreSQL $VERSION_POSTGRESQL ne semble pas installée." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fin des vérifications
|
||||
fancylog "INFO: fin des vérifications. Lancement des opérations."
|
||||
|
||||
|
||||
if [ "$MODE_CREATION" -eq 1 ]; then
|
||||
POSTGRESQL_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=10 status=noxfer | base64 | sed 's#[/=]##g' )
|
||||
POSTGRESQL_REPLICATION_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=20 status=noxfer | base64 | sed 's#[/=]##g' )
|
||||
# Création de l'instance dédiée
|
||||
fancylog "INFO: création du cluster PG primaire..."
|
||||
if [ -z "$POSTGRESQL_PORT" ]; then
|
||||
pg_createcluster --locale=$POSTGRESQL_LOCALE --start-conf=auto "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
|
||||
# Détermination du port généré
|
||||
# TODO: récupérer ça via pg_lsclusters serait plus "propre"
|
||||
POSTGRESQL_PORT=$( grep "^port" /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf | sed 's/^port[[:space:]]*=[[:space:]]*\([0-9]\+\).*$/\1/' )
|
||||
else
|
||||
pg_createcluster --locale=$POSTGRESQL_LOCALE --start-conf=auto --port "$POSTGRESQL_PORT" "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
|
||||
fi
|
||||
fancylog "INFO: modification du pg_hba.conf..."
|
||||
if ! generate_patch_postgresql_pghbaconf "$NOM_INSTANCE" | patch -s --dry-run /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf; then
|
||||
fancylog "ERREUR: modification du fichier pg_hba.conf en échec. Arrêt."
|
||||
exit 1
|
||||
fi
|
||||
generate_patch_postgresql_pghbaconf "$NOM_INSTANCE" | patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
|
||||
|
||||
fancylog "INFO: démarrage de l'instance PostgreSQL..."
|
||||
pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" start
|
||||
|
||||
# Lancement du script fourre-tout
|
||||
fancylog "INFO: création de l'utilisateur et de la base de données, et affinage des droits d'accès..."
|
||||
generate_script_postgresql_creation_db_et_user "$NOM_INSTANCE" "$POSTGRESQL_PASSWORD" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
|
||||
if [ -n "$ESCLAVE" ]; then
|
||||
fancylog "INFO: création de l'utilisateur de réplication..."
|
||||
generate_script_postgresql_creation_replication_user "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
|
||||
# configuration en tant que maître
|
||||
fancylog "INFO: modification de la configuration BDD de l'instance primaire..."
|
||||
if ! generate_patch_postgresqlconf_master "$ESCLAVE" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" | patch -s --dry-run /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf; then
|
||||
fancylog "ERREUR: modification du fichier postgresql.conf en échec. Arrêt."
|
||||
exit 1
|
||||
fi
|
||||
generate_patch_postgresqlconf_master "$ESCLAVE" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" | patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf
|
||||
# On rajoute les lignes pour la connexion streaming replication dans le pg_hba.conf
|
||||
echo "host replication $POSTGRESQL_REPLICATION_USER_NAME $ESCLAVE_WITH_MASK md5" >>/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
|
||||
echo "host replication $POSTGRESQL_REPLICATION_USER_NAME $MAITRE_WITH_MASK md5" >>/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
|
||||
|
||||
# Création sur l'esclave
|
||||
# Note: on commence par créer l'arborescence de l'esclave pour
|
||||
# avoir le répertoire de destination des archives logs
|
||||
# le plus tôt possible (en tout cas, avant le pg_stop_backup()
|
||||
# qui envoie forcément un WAL)
|
||||
fancylog "INFO: création du cluster PG secondaire..."
|
||||
ssh "root@$ESCLAVE" "cd /tmp; pg_createcluster --locale='$POSTGRESQL_LOCALE' -p '$POSTGRESQL_PORT' --start-conf=auto '$VERSION_POSTGRESQL' '$NOM_INSTANCE'"
|
||||
fancylog "INFO: création du dossier de réception des archives logs et arret du backup..."
|
||||
su -c "mkdir '/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/archives_from_master'" postgres
|
||||
su -c "ssh postgres@$ESCLAVE mkdir '/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/archives_from_master'" postgres
|
||||
|
||||
fancylog "INFO: redémarrage du serveur primaire..."
|
||||
pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" restart
|
||||
|
||||
# rsync du PGDATA vers l'esclave
|
||||
fancylog "INFO: écrasement du PGDATA secondaire par celui de l'instance primaire..."
|
||||
echo "SELECT pg_start_backup('script_mi_pg', true);" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
# on attend un peu, il y a parfois des fichiers WAL qui "vanished" pendant le rsync
|
||||
sleep 1
|
||||
# On exclut :
|
||||
# - postmaster.pid : raison évidente :)
|
||||
# - postmaster.opts : a priori, le contenu est identique mais par prudence...
|
||||
# - server.key/server.crt : rsync génère une erreur sur la date de modification des symlinks :-/
|
||||
# - recovery.* : le recovery.done du maitre référence l'esclave, et vice versa pour le recovery.conf de l'esclave
|
||||
# - archives_from_master : cela écraserait tout éventuel WAL déjà envoyé
|
||||
# - lost+found : au cas où la partition existe déjà (pg_createcluster se bloque mais ça permet de récupérer cette ligne de commande ailleurs :)
|
||||
# A étudier : pas de --delete ?
|
||||
# test -c car problème de synchro bizarre
|
||||
su -c "rsync -aHc --exclude=/postmaster.pid --exclude=/postmaster.opts --exclude=/server.key --exclude=/server.crt --exclude=/recovery.conf --exclude=/recovery.done --exclude=/archives_from_master --exclude=lost+found /var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/ postgres@$ESCLAVE:/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/" postgres
|
||||
echo "SELECT pg_stop_backup();" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
|
||||
# configuration de l'esclave
|
||||
fancylog "INFO: configuration de l'instance PG secondaire..."
|
||||
if ! ssh root@$ESCLAVE dpkg -s "postgresql-contrib-$VERSION_POSTGRESQL" >/dev/null 2>&1; then
|
||||
fancylog "WARNING: Le paquet postgresql-contrib-$VERSION_POSTGRESQL ne semble pas installé sur le serveur esclave, archive_cleanup_command sera désactivé." >&2
|
||||
fancylog "NOTICE: cf fichier /var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.conf en cas d'installation après-coup." >&2
|
||||
ARCHIVE_CLEANUP_COMMAND=""
|
||||
else
|
||||
# TODO: à rendre plus portable ?
|
||||
ARCHIVE_CLEANUP_COMMAND="/usr/lib/postgresql/$VERSION_POSTGRESQL/bin/pg_archivecleanup"
|
||||
fi
|
||||
generate_file_postgresqlrecoveryconf_slave "$MAITRE" "$POSTGRESQL_PORT" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" "$ARCHIVE_CLEANUP_COMMAND" | su -c "ssh postgres@$ESCLAVE 'cat - >/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.conf'" postgres
|
||||
generate_file_postgresqlrecoveryconf_slave "$ESCLAVE" "$POSTGRESQL_PORT" "$POSTGRESQL_REPLICATION_USER_NAME" "$POSTGRESQL_REPLICATION_PASSWORD" "$VERSION_POSTGRESQL" "$NOM_INSTANCE" "$ARCHIVE_CLEANUP_COMMAND" | su -c "cat - >/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/recovery.done" postgres
|
||||
generate_patch_postgresqlconf_slave | ssh "root@$ESCLAVE" patch -s /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/postgresql.conf
|
||||
# (note: même fichier pg_hba.conf pour tout le monde, homogénéisation avec peu de risques il me semble)
|
||||
scp -q /etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf root@$ESCLAVE:/etc/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/pg_hba.conf
|
||||
|
||||
# démarrage des instances maître et esclave
|
||||
fancylog "INFO: démarrage de l'instance PostgreSQL esclave..."
|
||||
ssh root@$ESCLAVE pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" start
|
||||
|
||||
# Vérification de la réplication
|
||||
# TODO (via numéro de transaction (requête) ? processus/connexion ?)
|
||||
fi
|
||||
|
||||
# Fin
|
||||
fancylog "INFO: Création terminée. Instance PostgreSQL allumée."
|
||||
fancylog "INFO: pour mémo :"
|
||||
fancylog "INFO: BDD: $NOM_INSTANCE, port: $POSTGRESQL_PORT, login: $NOM_INSTANCE, mdp: $POSTGRESQL_PASSWORD"
|
||||
TMP="$MAITRE"
|
||||
if [ -z "$MAITRE" ]; then
|
||||
TMP="localhost"
|
||||
fi
|
||||
fancylog "INFO: pgpass: $TMP:$POSTGRESQL_PORT:$NOM_INSTANCE:$NOM_INSTANCE:$POSTGRESQL_PASSWORD"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if [ "$MODE_DESTRUCTION" -eq 1 ]; then
|
||||
fancylog "INFO: suppression de l'instance locale..."
|
||||
# Note : en guise de garde-fou, on ne met pas l'option --stop
|
||||
pg_dropcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
|
||||
|
||||
if [ -n "$ESCLAVE" ]; then
|
||||
fancylog "INFO: suppression de l'instance esclave..."
|
||||
ssh root@$ESCLAVE pg_dropcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
453
oldies/script_multi-instance-tomcat.sh
Executable file
453
oldies/script_multi-instance-tomcat.sh
Executable file
|
@ -0,0 +1,453 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script sert à créer ou détruire une instance Tomcat
|
||||
# en créant un CATALINA_BASE indépendant.
|
||||
|
||||
# L'usage habituel se fait sur une Debian 7 "Wheezy" avec
|
||||
# tomcat, libapache2-mod-jk et apache2 installé.
|
||||
|
||||
# Prérequis :
|
||||
# - Debian Wheezy (Squeeze non testée)
|
||||
# - tomcat7 (6 non testée)
|
||||
# - libapache2-mod-jk avec le workers.properties du module
|
||||
|
||||
# Trucs à nettoyer (si quelque chose part en vrille, ou simplement
|
||||
# pour désinstaller ):
|
||||
# - supprimer tout le répertoire REP_TOMCAT_MULTIINSTANCE
|
||||
# - supprimer /etc/default/tomcatN_XXX
|
||||
# - supprimer /etc/init.d/tomcatN_XXX
|
||||
# - supprimer les utilisateurs tomcatN_YYYY
|
||||
# - nettoyer les clusters PostgreSQL
|
||||
|
||||
# Version de Tomcat : 6 ou 7
|
||||
# TODO : voir si on peut le passer en paramètre pour gérer
|
||||
# Tomcat 6 & 7 sur la même machine
|
||||
VERSION_TOMCAT="7"
|
||||
# Quelques constantes internes
|
||||
MAX_INSTANCES=999
|
||||
START_RANGE_TOMCATUID=8000
|
||||
START_RANGE_TOMCAT_PORT_SYS=15000
|
||||
START_RANGE_TOMCAT_PORT_HTTP=18000
|
||||
START_RANGE_TOMCAT_PORT_AJP=19000
|
||||
|
||||
# Initialisation des variables globales
|
||||
MODE_CREATION=0
|
||||
MODE_DESTRUCTION=0
|
||||
TOMCAT_ENABLE_SHUTDOWN_PORT=""
|
||||
OPTION_WORKERS_PROPERTIES=""
|
||||
OPTION_VHOST_APACHE_SERVERNAME=""
|
||||
NB_CHIFFRES_DANS_NUM_INSTANCE=$( printf "%d" "$MAX_INSTANCES" | wc -c )
|
||||
REP_TOMCAT_MULTIINSTANCE="/var/lib/tomcat$VERSION_TOMCAT-multiinstances"
|
||||
# On récupère également le nom de l'utilisateur et du groupe de Tomcat
|
||||
if [ ! -f /etc/default/tomcat$VERSION_TOMCAT ]; then
|
||||
echo "ERREUR: /etc/default/tomcat$VERSION_TOMCAT inaccessible." >&2
|
||||
exit 1
|
||||
fi
|
||||
. /etc/default/tomcat$VERSION_TOMCAT
|
||||
|
||||
# Par défaut, on arrête le script à la première erreur non "catchée"
|
||||
set -e
|
||||
|
||||
# Fonctions
|
||||
|
||||
# Arguments
|
||||
# $1 : Version de Tomcat
|
||||
# $2 : nom du worker
|
||||
# $3 : port AJP du worker
|
||||
ajout_worker_properties() {
|
||||
test -n "$1" && test -n "$2" && test -n "$3" || exit 1
|
||||
# On se fiche un peu de la version de Tomcat, en fait :)
|
||||
case "$1" in
|
||||
6|7)
|
||||
cat <<EOF
|
||||
|
||||
# Script MI Tomcat : ajout du worker $2
|
||||
worker.$2.port = $3
|
||||
worker.$2.host = localhost
|
||||
worker.$2.type = ajp13
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echo "ERREUR: version de Tomcat non-gérée." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1 : Version de Tomcat
|
||||
# $2 : port système (d'habitude 8005)
|
||||
# $3 : port connecteur HTTP (8080, d'habitude)
|
||||
# $4 : port connecteur AJP (8009, d'habitude)
|
||||
generate_patch_tomcat_server_xml() {
|
||||
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" && test -n "$5" || exit 1
|
||||
case "$1" in
|
||||
6|7)
|
||||
generate_patch_tomcat_server_xml_6 "$2" "$3" "$4" "$5"
|
||||
;;
|
||||
*)
|
||||
echo "ERREUR: version de Tomcat non-gérée." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1 : port système (d'habitude 8005)
|
||||
# $2 : port connecteur HTTP (8080, d'habitude)
|
||||
# $3 : port connecteur AJP (8009, d'habitude)
|
||||
generate_patch_tomcat_server_xml_6() {
|
||||
local NOM_WORKER TOMCAT_PORT_SYS TOMCAT_PORT_HTTP TOMCAT_PORT_AJP
|
||||
test -n "$1" && test -n "$2" && test -n "$3" && test -n "$4" || exit 1
|
||||
NOM_WORKER="$1"
|
||||
TOMCAT_PORT_SYS="$2"
|
||||
TOMCAT_PORT_HTTP="$3"
|
||||
TOMCAT_PORT_AJP="$4"
|
||||
cat <<EOF
|
||||
--- server.xml
|
||||
+++ server.xml
|
||||
@@ -19,7 +19,7 @@
|
||||
define subcomponents such as "Valves" at this level.
|
||||
Documentation at /docs/config/server.html
|
||||
-->
|
||||
-<Server port="8005" shutdown="SHUTDOWN">
|
||||
+<Server port="$TOMCAT_PORT_SYS" shutdown="SHUTDOWN">
|
||||
<!-- Security listener. Documentation at /docs/config/listeners.html
|
||||
<Listener className="org.apache.catalina.security.SecurityListener" />
|
||||
-->
|
||||
@@ -69,10 +69,12 @@
|
||||
APR (HTTP/AJP) Connector: /docs/apr.html
|
||||
Define a non-SSL HTTP/1.1 Connector on port 8080
|
||||
-->
|
||||
- <Connector port="8080" protocol="HTTP/1.1"
|
||||
+ <!--
|
||||
+ <Connector port="$TOMCAT_PORT_HTTP" protocol="HTTP/1.1"
|
||||
connectionTimeout="20000"
|
||||
URIEncoding="UTF-8"
|
||||
redirectPort="8443" />
|
||||
+ -->
|
||||
<!-- A "Connector" using the shared thread pool-->
|
||||
<!--
|
||||
<Connector executor="tomcatThreadPool"
|
||||
@@ -91,9 +93,7 @@
|
||||
-->
|
||||
|
||||
<!-- Define an AJP 1.3 Connector on port 8009 -->
|
||||
- <!--
|
||||
- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
|
||||
- -->
|
||||
+ <Connector port="$TOMCAT_PORT_AJP" protocol="AJP/1.3" redirectPort="8443" address="127.0.0.1" />
|
||||
|
||||
|
||||
<!-- An Engine represents the entry point (within Catalina) that processes
|
||||
@@ -105,7 +105,7 @@
|
||||
<!-- You should set jvmRoute to support load-balancing via AJP ie :
|
||||
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
|
||||
-->
|
||||
- <Engine name="Catalina" defaultHost="localhost">
|
||||
+ <Engine name="Catalina" defaultHost="localhost" jvmRoute="$NOM_WORKER">
|
||||
|
||||
<!--For clustering, please take a look at documentation at:
|
||||
/docs/cluster-howto.html (simple how to)
|
||||
EOF
|
||||
}
|
||||
|
||||
# Petites fonctions pour éviter de faire des concatenations
|
||||
# hasardeuses un peu partout
|
||||
get_tomcat_user() {
|
||||
case $VERSION_TOMCAT in
|
||||
'6')
|
||||
printf "%s" "$TOMCAT6_USER"
|
||||
;;
|
||||
'7')
|
||||
printf "%s" "$TOMCAT7_USER"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
get_tomcat_group() {
|
||||
# TODO : une idée à creuser serait de créer un groupe tomcat incluant tomcat6 et tomcat7
|
||||
case $VERSION_TOMCAT in
|
||||
'6')
|
||||
printf "%s" "$TOMCAT6_GROUP"
|
||||
;;
|
||||
'7')
|
||||
printf "%s" "$TOMCAT7_GROUP"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 -c suffixe
|
||||
$0 -d numero_instance
|
||||
$0 -h
|
||||
|
||||
-c xxxx : création d'une instance avec le suffixe 'xxxx' (15 caract. max)
|
||||
-d NNN : destruction de l'instance numéro NNN
|
||||
|
||||
-S : activation du port d'extinction de Tomcat
|
||||
(déconseillé en production, ne gêne pas le gestionnaire de démon de Debian :
|
||||
http://tomcat.apache.org/tomcat-7.0-doc/config/server.html#Common_Attributes
|
||||
http://wiki.apache.org/tomcat/FAQ/Security#Q2 )
|
||||
|
||||
|
||||
Ce script peut également modifier le fichier workers.properties
|
||||
pour y ajouter les infos du worker créé.
|
||||
-w /etc/.../workers.properties : Modification du workers.properties
|
||||
|
||||
-h : ce message d'aide
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts c:d:Sw:h f; do
|
||||
case $f in
|
||||
'c')
|
||||
MODE_CREATION=1
|
||||
SUFFIX="$OPTARG"
|
||||
|
||||
OLD_LC_ALL="$LC_ALL"
|
||||
export LC_ALL=C
|
||||
export LANG=C
|
||||
if [ $( printf "$SUFFIX" | egrep -c "^[a-z][a-z0-9_]{0,14}$" ) -ne 1 ]; then
|
||||
echo "ERREUR: suffixe vide ou contenant des caractères interdits : regexp : [a-z][a-z0-9_]{0,14}" >&2
|
||||
exit 1
|
||||
fi
|
||||
export LC_ALL="$OLD_LC_ALL"
|
||||
export LANG="$OLD_LC_ALL"
|
||||
;;
|
||||
|
||||
'd')
|
||||
MODE_DESTRUCTION=1
|
||||
NUM_INSTANCE=$( printf "%d" "$OPTARG" )
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
'S')
|
||||
TOMCAT_ENABLE_SHUTDOWN_PORT="1"
|
||||
;;
|
||||
|
||||
'w')
|
||||
OPTION_WORKERS_PROPERTIES="$OPTARG"
|
||||
if [ ! -f "$OPTION_WORKERS_PROPERTIES" ]; then
|
||||
echo "ERREUR: fichier workers.properties inexistant : $OPTION_WORKERS_PROPERTIES" >&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
#(code inutile pour ce script, mais que je garde parce qu'on ne sait jamais)
|
||||
#shift $( expr $OPTIND - 1 )
|
||||
#DATA="$1"
|
||||
|
||||
# Petite vérif.
|
||||
case $(( $MODE_CREATION + $MODE_DESTRUCTION )) in
|
||||
'0')
|
||||
echo "ERREUR: veuillez choisir entre création et destruction." >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
'2')
|
||||
echo "ERREUR: tu veux créer et détruire en même temps, petit malin ?" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# - est-ce qu'on est bien sur une Debian 6 ou 7
|
||||
# (c'est surtout pour éviter les mauvaises surprises, ce script n'ayant pas été testé ailleurs)
|
||||
if [ ! -f "/etc/debian_version" ] || [ $( egrep -c "^(6.|7.)" /etc/debian_version ) -ne 1 ]; then
|
||||
echo "ERREUR: mauvaise version de Debian détectée. Arrêt par prudence. Vérifiez le code de ce script avant de forcer." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# - est-ce que Tomcat est bien installé ?
|
||||
if ! dpkg -l tomcat$VERSION_TOMCAT >/dev/null 2>&1; then
|
||||
echo "ERREUR: tomcat$VERSION_TOMCAT ne semble pas avoir été installé." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# - on vérifie que le /etc/default/tomcatN contient bien les infos qui nous intéresse
|
||||
if [ ! -n $( get_tomcat_user ) ] || [ ! -n $( get_tomcat_group) ]; then
|
||||
echo "ERREUR: TOMCAT_USER ou TOMCAT_GROUP indeterminé." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fin des vérifications
|
||||
|
||||
|
||||
if [ "$MODE_CREATION" -eq 1 ]; then
|
||||
# Détermination du numéro d'instance :
|
||||
# On cherche un numéro inutilisé ni par une instance Tomcat, ni par une instance Postgres
|
||||
for NUM_INSTANCE in $( seq 1 $MAX_INSTANCES ); do
|
||||
# Finalement, on base tout sur le nom de l'instance : ça
|
||||
# nous permet de retrouver facilement le répertoire de l'instance
|
||||
# lors de la suppression (le HOME de tomcat7 est sur CATALINA_HOME,
|
||||
# pas sur CATALINA_BASE :'(
|
||||
NOM_INSTANCE=$( printf "%s_%0$NB_CHIFFRES_DANS_NUM_INSTANCE""d_%s" "$( get_tomcat_user )" "$NUM_INSTANCE" "$SUFFIX" )
|
||||
USERID_TOMCAT=$(( $START_RANGE_TOMCATUID + $NUM_INSTANCE ))
|
||||
USERNAME_TOMCAT="$NOM_INSTANCE"
|
||||
SCRIPTNAME_TOMCAT="$NOM_INSTANCE"
|
||||
WORKERNAME_TOMCAT="worker_$NOM_INSTANCE"
|
||||
if [ ! -d "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE" ] && ! getent passwd "$USERID_TOMCAT" >/dev/null 2>&1 && ! getent passwd "$USERNAME_TOMCAT" >/dev/null 2>&1; then
|
||||
echo "INFO: Numéro d'instance libre trouvé : $NUM_INSTANCE"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$NUM_INSTANCE" -eq "$MAX_INSTANCES" ]; then
|
||||
echo "ERREUR: plus de numéro d'instance disponible." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier que le REP_TOMCAT_MULTIINSTANCE pré-existe.
|
||||
# TODO review : finalement pas une bonne idée de le faire créer par le script ?
|
||||
if [ ! -d "$REP_TOMCAT_MULTIINSTANCE" ]; then
|
||||
# (finalement, on le crée nous même...)
|
||||
echo "WARNING: le répertoire '$REP_TOMCAT_MULTIINSTANCE' n'existe pas (normal si première exécution). Création..."
|
||||
mkdir -p "$REP_TOMCAT_MULTIINSTANCE"
|
||||
chown -R "root:$( get_tomcat_group )" "$REP_TOMCAT_MULTIINSTANCE"
|
||||
chmod 750 "$REP_TOMCAT_MULTIINSTANCE"
|
||||
fi
|
||||
|
||||
# Copie du script d'init et du /etc/default de Tomcat
|
||||
# Note : pour les scripts d'init, j'aurais aimé faire de simples liens symboliques vers
|
||||
# un script générique. Malheureusement, ça pose de gros soucis pour LSB (insserv
|
||||
# semble avoir les liens symboliques en horreur) et on aurait dû tout faire à la
|
||||
# main, d'où plus d'inconvénients que d'avantages.
|
||||
echo "INFO: création de l'utilisateur système dédié..."
|
||||
useradd -u "$USERID_TOMCAT" -s /bin/false -g $( get_tomcat_group ) -d $( getent passwd $( get_tomcat_user ) | cut -d : -f 6 ) "$USERNAME_TOMCAT"
|
||||
echo "INFO: création du script de lancement..."
|
||||
cat /etc/init.d/tomcat$VERSION_TOMCAT | \
|
||||
sed "s/^\(#[[:space:]]*Provides[[:space:]]*:[[:space:]]*\)tomcat[0-9]\+[[:space:]]*$/\1$SCRIPTNAME_TOMCAT/" | \
|
||||
sed 's/^NAME=tomcat[0-9]\+$/NAME=$( basename "$0" | sed "s\/^[SK][0-9]\+\/\/" )/' \
|
||||
>/etc/init.d/$SCRIPTNAME_TOMCAT
|
||||
chmod +x /etc/init.d/$SCRIPTNAME_TOMCAT
|
||||
echo "INFO: création du fichier de paramétrage dans /etc/default..."
|
||||
cat /etc/default/tomcat$VERSION_TOMCAT | sed "s/^\(TOMCAT[0-9]\+_USER\)=tomcat[0-9]\+$/\1=$USERNAME_TOMCAT/" >/etc/default/$SCRIPTNAME_TOMCAT
|
||||
echo "# Script MI Tomcat : Spécification des CATALINA_HOME et CATALINA_BASE" >>/etc/default/$SCRIPTNAME_TOMCAT
|
||||
echo "CATALINA_HOME=/usr/share/tomcat$VERSION_TOMCAT" >>/etc/default/$SCRIPTNAME_TOMCAT
|
||||
echo "CATALINA_BASE=$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE" >>/etc/default/$SCRIPTNAME_TOMCAT
|
||||
|
||||
# Activation du script d'init
|
||||
echo "INFO: activation du script d'init..."
|
||||
update-rc.d $SCRIPTNAME_TOMCAT defaults
|
||||
|
||||
|
||||
# Instanciation du CATALINA_BASE
|
||||
# Copie du /var/lib/tomcatN (notre template, en gros)
|
||||
echo "INFO: génération du CATALINA_BASE ( $REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE )..."
|
||||
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
|
||||
cp -a /var/lib/tomcat$VERSION_TOMCAT/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/"
|
||||
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf"
|
||||
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs"
|
||||
rm "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work"
|
||||
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf"
|
||||
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs"
|
||||
mkdir "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work"
|
||||
cp -r /var/lib/tomcat$VERSION_TOMCAT/conf/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf/"
|
||||
# Parfois, le work est vide. Solution temporaire : on émet un warning
|
||||
if [ "$( ls /var/lib/tomcat$VERSION_TOMCAT/work/* 2>/dev/null | wc -l )" -gt 0 ]; then
|
||||
cp -r /var/lib/tomcat$VERSION_TOMCAT/work/* "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/work/"
|
||||
else
|
||||
echo "INFO: le répertoire /work/ du template est vide. A priori, c'est normal."
|
||||
fi
|
||||
chown -R $USERNAME_TOMCAT:$( get_tomcat_group ) "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
|
||||
|
||||
# Réglage des ports TCP/IP
|
||||
generate_patch_tomcat_server_xml "$VERSION_TOMCAT" \
|
||||
"$WORKERNAME_TOMCAT" \
|
||||
$( test -n "$TOMCAT_ENABLE_SHUTDOWN_PORT" && echo $(( $START_RANGE_TOMCAT_PORT_SYS + $NUM_INSTANCE )) || echo "-1" ) \
|
||||
$(( $START_RANGE_TOMCAT_PORT_HTTP + $NUM_INSTANCE )) \
|
||||
$(( $START_RANGE_TOMCAT_PORT_AJP + $NUM_INSTANCE )) | \
|
||||
patch $REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/conf/server.xml
|
||||
|
||||
# Génération du fichier de config de logrotate
|
||||
echo "INFO: génération du logrotate..."
|
||||
cat /etc/logrotate.d/tomcat$VERSION_TOMCAT | \
|
||||
sed "s#^/var/log/tomcat[0-9]\+/catalina.out #$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE/logs/catalina.out #" | \
|
||||
sed "s/create 640 tomcat[0-9]\+ adm/create 640 $USERNAME_TOMCAT adm/" \
|
||||
>/etc/logrotate.d/$SCRIPTNAME_TOMCAT
|
||||
|
||||
# partie annexe n°1 : workers.properties
|
||||
if [ -f "$OPTION_WORKERS_PROPERTIES" ]; then
|
||||
echo "INFO: Modification du workers.properties..."
|
||||
# Ajout du worker à la worker.list
|
||||
TMP_SUFFIX=$( date +%Y%m%d-%H%M%S )
|
||||
sed -i.$TMP_SUFFIX -e "s/^worker.list=\(.\+\)$/worker.list=\1,$WORKERNAME_TOMCAT/g" -e "s/^worker.list=$/worker.list=$WORKERNAME_TOMCAT/g" "$OPTION_WORKERS_PROPERTIES"
|
||||
echo "NOTICE: une sauvegarde $OPTION_WORKERS_PROPERTIES.$TMP_SUFFIX a été créée, n'hésitez pas à la supprimer."
|
||||
|
||||
# Ajouts de la définition du worker
|
||||
ajout_worker_properties "$VERSION_TOMCAT" "$WORKERNAME_TOMCAT" $(( $START_RANGE_TOMCAT_PORT_AJP + $NUM_INSTANCE )) >> "$OPTION_WORKERS_PROPERTIES"
|
||||
fi
|
||||
|
||||
# Fin
|
||||
echo "INFO: Création terminée. Serveur Tomcat éteint."
|
||||
echo "INFO: Pour connecter mod-jk au worker, voici la ligne à ajouter au vhost : JkMount /* $WORKERNAME_TOMCAT"
|
||||
echo "INFO: Pour allumer l'instance Tomcat : service $SCRIPTNAME_TOMCAT start"
|
||||
fi
|
||||
|
||||
if [ "$MODE_DESTRUCTION" -eq 1 ]; then
|
||||
USERID_TOMCAT=$(( $START_RANGE_TOMCATUID + $NUM_INSTANCE ))
|
||||
|
||||
#echo "NOTICE: le script est en mode -e. Il s'arrête donc à la première erreur. Le cas échéant, il faudra terminer le nettoyage à la main."
|
||||
|
||||
# On recherche le nom de l'instance
|
||||
USERNAME_TOMCAT=$( getent passwd $USERID_TOMCAT | cut -d : -f 1 )
|
||||
NOM_INSTANCE="$USERNAME_TOMCAT"
|
||||
SCRIPTNAME_TOMCAT="$NOM_INSTANCE"
|
||||
WORKERNAME_TOMCAT="worker_$NOM_INSTANCE"
|
||||
|
||||
if [ ! -n "$USERNAME_TOMCAT" ]; then
|
||||
echo "ERREUR: l'utilisateur correspondant à l'uid $USERID_TOMCAT est introuvable." >&2
|
||||
exit 1
|
||||
fi
|
||||
if service "$SCRIPTNAME_TOMCAT" status >/dev/null 2>&1; then
|
||||
echo "ERREUR: l'instance tomcat tourne toujours. Ne pas oublier le service $SCRIPTNAME_TOMCAT stop" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Suppression utilisateur et répertoire dédié
|
||||
echo "INFO: suppression de l'utilisateur..."
|
||||
userdel $USERNAME_TOMCAT
|
||||
echo "INFO: suppression du répertoire dédié..."
|
||||
rm -rf "$REP_TOMCAT_MULTIINSTANCE/$NOM_INSTANCE"
|
||||
echo "INFO: suppresion fichier default..."
|
||||
rm -f "/etc/default/$SCRIPTNAME_TOMCAT"
|
||||
|
||||
# Suppression du script d'init
|
||||
echo "INFO: désactivation et suppression du script d'init..."
|
||||
rm -f /etc/init.d/$SCRIPTNAME_TOMCAT
|
||||
update-rc.d "$SCRIPTNAME_TOMCAT" remove
|
||||
|
||||
# Suppression logrotate
|
||||
echo "INFO: suppression logrotate..."
|
||||
rm -f /etc/logrotate.d/$SCRIPTNAME_TOMCAT
|
||||
|
||||
# partie annexe n°1 : workers.properties
|
||||
if [ -f "$OPTION_WORKERS_PROPERTIES" ]; then
|
||||
echo "INFO: Modification du workers.properties..."
|
||||
# Soustraction de la définition du worker
|
||||
TMP_SUFFIX=$( date +%Y%m%d-%H%M%S )
|
||||
sed -i.$TMP_SUFFIX -e "/^worker.list=/s/$WORKERNAME_TOMCAT[,]\?//g" \
|
||||
-e '/^worker.list=.*,$/s/,$//' \
|
||||
-e "/^# Script MI Tomcat : ajout du worker $WORKERNAME_TOMCAT$/d" \
|
||||
-e "/^worker.$WORKERNAME_TOMCAT/d" \
|
||||
"$OPTION_WORKERS_PROPERTIES"
|
||||
echo "NOTICE: une sauvegarde $OPTION_WORKERS_PROPERTIES.$TMP_SUFFIX a été créée, n'hésitez pas à la supprimer."
|
||||
fi
|
||||
|
||||
# Fin
|
||||
echo "INFO: suppression terminée."
|
||||
fi
|
23
oldies/script_multi-pg-comparaison-instances.sh
Executable file
23
oldies/script_multi-pg-comparaison-instances.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
|
||||
ESCLAVE="a.b.c.d"
|
||||
|
||||
for i in $@; do
|
||||
# On récupère le numéro de port
|
||||
POSTGRESQL_PORT="$( pg_lsclusters | sed 's/[[:space:]]\+/ /g' | cut -f 2,3 -d ' ' | grep -w "$i" | cut -f 2 -d ' ' )"
|
||||
if [ -z "$POSTGRESQL_PORT" ]; then
|
||||
echo "ERREUR: pas de port trouvé pour '$i'." >&2
|
||||
continue
|
||||
fi
|
||||
|
||||
# dump1 : local
|
||||
DUMP1=$( mktemp local-XXXX )
|
||||
DUMP2=$( mktemp distant-XXXXX )
|
||||
su -l -c "pg_dumpall -p $POSTGRESQL_PORT" postgres > $DUMP1
|
||||
su -l -c "ssh postgres@$ESCLAVE pg_dumpall -p $POSTGRESQL_PORT" postgres > $DUMP2
|
||||
echo "$i..."
|
||||
diff -u "$DUMP1" "$DUMP2"
|
||||
rm -f "$DUMP1" "$DUMP2"
|
||||
done
|
59
oldies/script_multi-pg-deuxieme-utilisateur.sh
Executable file
59
oldies/script_multi-pg-deuxieme-utilisateur.sh
Executable file
|
@ -0,0 +1,59 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script génère juste du SQL permettant, à partir
|
||||
# du résultat du script multi-pg, de renommer l'utilisateur
|
||||
# de l'instance en instance_admin et de lui donner les
|
||||
# droits nécessaires au bon fonctionnement de phppgadmin,
|
||||
# et de créer un utilisateur instance avec des droits
|
||||
# encore plus limités (pas de modif de la structure, seulement
|
||||
# select,insert,update,delete et gestion des séquences)
|
||||
#
|
||||
# TODO: message d'aide pour les arguments:
|
||||
# script.sh nom_instance ancien_mot_de_passe
|
||||
# TODO 2: essayer d'éviter le mot de passe dans la ligne de commande :-(
|
||||
|
||||
set -e
|
||||
|
||||
# Arguments:
|
||||
# $1 : Nom de la bdd / de l'utilisateur
|
||||
# $2 : mot de passe de l'utilisateur
|
||||
# $3 : nom de l'utilisateur dédié à la réplication
|
||||
# $4 : mot de passe dudit utilisateur
|
||||
generate_script_postgresql_creation_db_et_user() {
|
||||
local NOM_INSTANCE POSTGRESQL_PASSWORD ADMIN_PASSWORD
|
||||
test -n "$1" && test -n "$2" && test -n "$3" || exit 1
|
||||
NOM_INSTANCE="$1"
|
||||
POSTGRESQL_PASSWORD="$2"
|
||||
ADMIN_PASSWORD="$3"
|
||||
ADMIN_USERNAME="$NOM_INSTANCE""_admin"
|
||||
cat <<EOF
|
||||
ALTER USER $NOM_INSTANCE RENAME TO $ADMIN_USERNAME;
|
||||
|
||||
ALTER USER $ADMIN_USERNAME WITH PASSWORD '$ADMIN_PASSWORD';
|
||||
|
||||
-- Re-création de l'utilisateur normal
|
||||
CREATE USER $NOM_INSTANCE WITH PASSWORD '$POSTGRESQL_PASSWORD' CONNECTION LIMIT 50;
|
||||
GRANT CONNECT ON DATABASE $NOM_INSTANCE TO $NOM_INSTANCE;
|
||||
|
||||
\c $NOM_INSTANCE
|
||||
GRANT USAGE ON SCHEMA public TO $NOM_INSTANCE;
|
||||
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA public TO $NOM_INSTANCE;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $ADMIN_USERNAME IN SCHEMA public GRANT select,insert,update,delete ON TABLES TO $NOM_INSTANCE;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $ADMIN_USERNAME IN SCHEMA public GRANT USAGE,UPDATE ON SEQUENCES TO $NOM_INSTANCE;
|
||||
|
||||
-- Ce passage-là est plus parano, mais à étudier avant suppression
|
||||
GRANT SELECT ON pg_user TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_roles TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_group TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_authid TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_auth_members TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_database TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_tablespace TO $ADMIN_USERNAME;
|
||||
GRANT SELECT ON pg_settings TO $ADMIN_USERNAME;
|
||||
EOF
|
||||
}
|
||||
|
||||
NOM_INSTANCE="$1"
|
||||
POSTGRESQL_PASSWORD="$2"
|
||||
ADMIN_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=10 status=noxfer | base64 | sed 's#[/=]##g' )
|
||||
generate_script_postgresql_creation_db_et_user "$NOM_INSTANCE" "$POSTGRESQL_PASSWORD" "$ADMIN_PASSWORD"
|
86
oldies/script_multi-pg-reset.sh
Executable file
86
oldies/script_multi-pg-reset.sh
Executable file
|
@ -0,0 +1,86 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
generate_dump() {
|
||||
test -n "$1" || exit 1
|
||||
cat <<EOF
|
||||
--
|
||||
-- PostgreSQL database cluster dump
|
||||
--
|
||||
|
||||
\connect postgres
|
||||
|
||||
|
||||
--
|
||||
-- Database creation
|
||||
--
|
||||
|
||||
CREATE DATABASE $1 WITH TEMPLATE = template0 OWNER = $1_admin;
|
||||
REVOKE ALL ON DATABASE $1 FROM PUBLIC;
|
||||
REVOKE ALL ON DATABASE $1 FROM $1_admin;
|
||||
GRANT ALL ON DATABASE $1 TO $1_admin;
|
||||
GRANT CONNECT ON DATABASE $1 TO $1;
|
||||
REVOKE ALL ON DATABASE template1 FROM PUBLIC;
|
||||
REVOKE ALL ON DATABASE template1 FROM postgres;
|
||||
GRANT ALL ON DATABASE template1 TO postgres;
|
||||
|
||||
|
||||
\connect $1
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SET check_function_bodies = false;
|
||||
SET client_min_messages = warning;
|
||||
|
||||
--
|
||||
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner:
|
||||
--
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||||
|
||||
|
||||
--
|
||||
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner:
|
||||
--
|
||||
|
||||
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
|
||||
|
||||
|
||||
--
|
||||
-- Name: public; Type: ACL; Schema: -; Owner: postgres
|
||||
--
|
||||
|
||||
REVOKE ALL ON SCHEMA public FROM PUBLIC;
|
||||
REVOKE ALL ON SCHEMA public FROM postgres;
|
||||
GRANT ALL ON SCHEMA public TO postgres;
|
||||
GRANT ALL ON SCHEMA public TO $1_admin;
|
||||
GRANT USAGE ON SCHEMA public TO $1;
|
||||
|
||||
|
||||
SET search_path = public, pg_catalog;
|
||||
|
||||
--
|
||||
-- Name: DEFAULT PRIVILEGES FOR SEQUENCES; Type: DEFAULT ACL; Schema: public; Owner: $1_admin
|
||||
--
|
||||
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM PUBLIC;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM $1_admin;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public GRANT USAGE,UPDATE ON SEQUENCES TO $1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: DEFAULT PRIVILEGES FOR TABLES; Type: DEFAULT ACL; Schema: public; Owner: $1_admin
|
||||
--
|
||||
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public REVOKE ALL ON TABLES FROM PUBLIC;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public REVOKE ALL ON TABLES FROM $1_admin;
|
||||
ALTER DEFAULT PRIVILEGES FOR ROLE $1_admin IN SCHEMA public GRANT SELECT,INSERT,DELETE,UPDATE ON TABLES TO $1;
|
||||
EOF
|
||||
}
|
||||
|
||||
generate_dump "$1"
|
66
oldies/script_multi-pg-reutilisation-ancien-master.sh
Executable file
66
oldies/script_multi-pg-reutilisation-ancien-master.sh
Executable file
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Script en version alpha-brouillon
|
||||
# À n'utiliser qu'en connaissance de cause et avec
|
||||
# une parfaite maîtrise du fonctionnement de la SR
|
||||
|
||||
# config sur MAITRE inutile ici
|
||||
MAITRE=""
|
||||
ESCLAVE="a.b.c.d"
|
||||
|
||||
set -e
|
||||
|
||||
# on ne peut pas faire le | while read avec du ssh dans la boucle ??
|
||||
#for NOM_INSTANCE in $( pg_lsclusters -h | sed 's/[[:space:]]\+/ /g' | cut -d ' ' -f 2 ); do
|
||||
for NOM_INSTANCE in $@; do
|
||||
# Récupération de la ligne 'pg_lsclusters' complète
|
||||
LINE="$( pg_lsclusters -h | sed 's/[[:space:]]\+/ /g' | egrep "^[0-9.]+ $NOM_INSTANCE " )"
|
||||
if [ -z "$LINE" ]; then
|
||||
echo "ERREUR: instance '$NOM_INSTANCE' inexistante." >&2
|
||||
exit 1
|
||||
fi
|
||||
# Découpage des éléments de ladite ligne
|
||||
VERSION_POSTGRESQL="$( echo "$LINE" | cut -d ' ' -f 1 )"
|
||||
POSTGRESQL_PORT="$( echo "$LINE" | cut -d ' ' -f 3 )"
|
||||
STATUT="$( echo "$LINE" | cut -d ' ' -f 4 )"
|
||||
POSTGRESQL_PGDATA="$( echo "$LINE" | cut -d ' ' -f 6 )"
|
||||
|
||||
# On ne s'occupe que des instances "online" pures
|
||||
if [ "$( echo "$LINE" | cut -d ' ' -f 4 )" != "online" ]; then
|
||||
echo "NOTICE: on ignore l'instance '$NOM_INSTANCE' dont le statut ('$STATUT') n'est pas 'online'."
|
||||
continue
|
||||
fi
|
||||
|
||||
# On vérifie que l'instance en face est bien éteinte
|
||||
if [ "$( ssh root@$ESCLAVE pg_lsclusters -h | grep -w "$NOM_INSTANCE" | grep online | wc -l )" -ne 0 ]; then
|
||||
echo "NOTICE: l'instance '$NOM_INSTANCE' semble toujours allumée sur le serveur distant. On l'ignore."
|
||||
continue
|
||||
fi
|
||||
# ...et on vérifie que le fichier recovery.done est dispo
|
||||
if ! su -c "ssh postgres@$ESCLAVE test -f $POSTGRESQL_PGDATA/recovery.done" postgres; then
|
||||
echo "NOTICE: le fichier recovery.done ne semble pas dispo pour l'instance distante '$NOM_INSTANCE'."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "INFO: resynchro de l'instance '$NOM_INSTANCE'..."
|
||||
|
||||
# Marquage
|
||||
echo "INFO: rsync..."
|
||||
echo "SELECT pg_start_backup('resynchro_maitre', true);" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
# Resynchro des fichiers
|
||||
sleep 1
|
||||
su -c "rsync -aHc --exclude=/postmaster.pid --exclude=/postmaster.opts --exclude=/server.key --exclude=/server.crt --exclude=/recovery.conf --exclude=/recovery.done --exclude=/archives_from_master --exclude=lost+found /var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/ postgres@$ESCLAVE:/var/lib/postgresql/$VERSION_POSTGRESQL/$NOM_INSTANCE/" postgres
|
||||
# Vidange du dossier 'archives_from_master' distant, par prudence
|
||||
su -c "ssh postgres@$ESCLAVE rm -rvf $POSTGRESQL_PGDATA/archives_from_master/*" postgres
|
||||
sleep 1
|
||||
echo "SELECT pg_stop_backup();" | su -c "psql -p $POSTGRESQL_PORT -v ON_ERROR_STOP=1" postgres
|
||||
|
||||
# Renommage du fichier recovery.conf distant pour activation
|
||||
echo "INFO: renommage recovery.done distant en .conf..."
|
||||
su -c "ssh postgres@$ESCLAVE mv -v $POSTGRESQL_PGDATA/recovery.done $POSTGRESQL_PGDATA/recovery.conf" postgres
|
||||
|
||||
# Démarrage instance distante
|
||||
ssh root@$ESCLAVE pg_ctlcluster "$VERSION_POSTGRESQL" "$NOM_INSTANCE" start
|
||||
done
|
||||
|
||||
echo "The end."
|
409
oldies/script_preparation-vz-drupal.sh
Executable file
409
oldies/script_preparation-vz-drupal.sh
Executable file
|
@ -0,0 +1,409 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce petit script customise une VZ Debian 7
|
||||
# pour préparer l'arrivée d'un Drupal :
|
||||
# - install Apache/PHP
|
||||
# - install mysql ou postgresql
|
||||
# - install éventuelle de PHPMyAdmin/PHPPgAdmin
|
||||
|
||||
TYPE_BDD=""
|
||||
INSTALL_PHPBDDADMIN=""
|
||||
INSTALL_DRUSH=""
|
||||
BDD_CONNEXIONS_OPEN_BAR=""
|
||||
NOM_UTILISATEUR="deploy"
|
||||
|
||||
# Arrêt à la première erreur non-catchée
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [{ -m | -p } [ -l ] [ -a ]] nom_site
|
||||
$0 -h
|
||||
|
||||
-m : site avec MySQL
|
||||
-p : site avec PostgreSQL
|
||||
-a : ajout de PHPMyAdmin / PHPPgAdmin
|
||||
-l : ouverture des connexions à la BDD depuis le LAN
|
||||
-d : install drush via php-pear
|
||||
nom_site : pseudo du site à créer (nom du répertoire et du fichier du vhost)
|
||||
|
||||
-h : ce message d'aide
|
||||
EOF
|
||||
}
|
||||
|
||||
patch_apache_default_vhost() {
|
||||
cat <<EOF
|
||||
diff --git a/apache2/sites-available/default b/apache2/sites-available/default
|
||||
index b0703f5..3efc3dd 100644
|
||||
--- a/apache2/sites-available/default
|
||||
+++ b/apache2/sites-available/default
|
||||
@@ -1,26 +1,18 @@
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@localhost
|
||||
|
||||
- DocumentRoot /var/www
|
||||
+ DocumentRoot /var/www/default
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
</Directory>
|
||||
- <Directory /var/www/>
|
||||
+ <Directory /var/www/default/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
- ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
|
||||
- <Directory "/usr/lib/cgi-bin">
|
||||
- AllowOverride None
|
||||
- Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
- Order allow,deny
|
||||
- Allow from all
|
||||
- </Directory>
|
||||
-
|
||||
ErrorLog \${APACHE_LOG_DIR}/error.log
|
||||
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
diff --git a/apache2/sites-available/default-ssl b/apache2/sites-available/default-ssl
|
||||
index ea454b8..cca8e63 100644
|
||||
--- a/apache2/sites-available/default-ssl
|
||||
+++ b/apache2/sites-available/default-ssl
|
||||
@@ -2,26 +2,18 @@
|
||||
<VirtualHost _default_:443>
|
||||
ServerAdmin webmaster@localhost
|
||||
|
||||
- DocumentRoot /var/www
|
||||
+ DocumentRoot /var/www/default
|
||||
<Directory />
|
||||
Options FollowSymLinks
|
||||
AllowOverride None
|
||||
</Directory>
|
||||
- <Directory /var/www/>
|
||||
+ <Directory /var/www/default/>
|
||||
Options Indexes FollowSymLinks MultiViews
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
- ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
|
||||
- <Directory "/usr/lib/cgi-bin">
|
||||
- AllowOverride None
|
||||
- Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||
- Order allow,deny
|
||||
- Allow from all
|
||||
- </Directory>
|
||||
-
|
||||
ErrorLog \${APACHE_LOG_DIR}/error.log
|
||||
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
EOF
|
||||
}
|
||||
|
||||
patch_mysql_access_from_lan() {
|
||||
cat <<EOF
|
||||
diff --git a/mysql/my.cnf b/mysql/my.cnf
|
||||
index 1f96915..94ea010 100644
|
||||
--- a/mysql/my.cnf
|
||||
+++ b/mysql/my.cnf
|
||||
@@ -44,7 +44,7 @@ skip-external-locking
|
||||
#
|
||||
# Instead of skip-networking the default is now to listen only on
|
||||
# localhost which is more compatible and is not less secure.
|
||||
-bind-address = 127.0.0.1
|
||||
+#bind-address = 127.0.0.1
|
||||
#
|
||||
# * Fine Tuning
|
||||
#
|
||||
EOF
|
||||
}
|
||||
|
||||
patch_phpmyadmin_access_from_lan() {
|
||||
cat <<EOF
|
||||
diff --git a/phpmyadmin/apache.conf b/phpmyadmin/apache.conf
|
||||
index 415acb9..7f274a3 100644
|
||||
--- a/phpmyadmin/apache.conf
|
||||
+++ b/phpmyadmin/apache.conf
|
||||
@@ -1,11 +1,14 @@
|
||||
# phpMyAdmin default Apache configuration
|
||||
|
||||
-Alias /phpmyadmin /usr/share/phpmyadmin
|
||||
+#Alias /phpmyadmin /usr/share/phpmyadmin
|
||||
|
||||
<Directory /usr/share/phpmyadmin>
|
||||
Options FollowSymLinks
|
||||
DirectoryIndex index.php
|
||||
|
||||
+ Order allow,deny
|
||||
+ Allow from 172.20.0.0/16
|
||||
+
|
||||
<IfModule mod_php5.c>
|
||||
AddType application/x-httpd-php .php
|
||||
|
||||
diff --git a/apache2/sites-available/phpmyadmin b/apache2/sites-available/phpmyadmin
|
||||
new file mode 100644
|
||||
index 0000000..8d81d37
|
||||
--- /dev/null
|
||||
+++ b/apache2/sites-available/phpmyadmin
|
||||
@@ -0,0 +1,23 @@
|
||||
+<VirtualHost *:80>
|
||||
+ ServerAdmin webmaster@localhost
|
||||
+
|
||||
+ DocumentRoot /usr/share/phpmyadmin
|
||||
+
|
||||
+ Include /etc/apache2/conf.d/phpmyadmin.conf
|
||||
+
|
||||
+ ServerName phpmyadmin
|
||||
+ ServerAlias phpmyadmin.*
|
||||
+
|
||||
+ <Directory />
|
||||
+ Options FollowSymLinks
|
||||
+ AllowOverride None
|
||||
+ </Directory>
|
||||
+
|
||||
+ ErrorLog \${APACHE_LOG_DIR}/phpmyadmin_error.log
|
||||
+
|
||||
+ # Possible values include: debug, info, notice, warn, error, crit,
|
||||
+ # alert, emerg.
|
||||
+ LogLevel warn
|
||||
+
|
||||
+ CustomLog \${APACHE_LOG_DIR}/phpmyadmin_access.log combined
|
||||
+</VirtualHost>
|
||||
EOF
|
||||
}
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts almpdh f; do
|
||||
case $f in
|
||||
'a')
|
||||
INSTALL_PHPBDDADMIN="true"
|
||||
;;
|
||||
|
||||
'l')
|
||||
BDD_CONNEXIONS_OPEN_BAR="yes"
|
||||
;;
|
||||
|
||||
'm')
|
||||
TYPE_BDD="mysql"
|
||||
;;
|
||||
|
||||
'p')
|
||||
TYPE_BDD="postgresql"
|
||||
;;
|
||||
|
||||
'd')
|
||||
INSTALL_DRUSH="true"
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
#(code inutile, mais que je garde parce qu'on ne sait jamais)
|
||||
shift $( expr $OPTIND - 1 )
|
||||
NOM_SITE="$1"
|
||||
|
||||
# On part dans le répertoire de travail
|
||||
cd /etc
|
||||
|
||||
# Petites vérifications
|
||||
if [ -z "$NOM_SITE" ]; then
|
||||
echo "ERREUR: veuillez donner un identifiant au site." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -z "$INSTALL_PHPBDDADMIN" ] && [ -z "$TYPE_BDD" ]; then
|
||||
echo "ERREUR: veuillez choisir PostgreSQL/MySQL." >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! git status >/dev/null 2>&1 || [ $( git status --porcelain | wc -l ) -gt 0 ]; then
|
||||
echo "ERREUR: travaux non-commités dans /etc." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Installation des paquets communs
|
||||
# (note: php5-mcrypt est une dépendance de phpmyadmin. On le met par défaut pour éviter
|
||||
# des disparités dans les install dev/prod)
|
||||
echo "INFO: aptitude update..."
|
||||
aptitude update
|
||||
echo "INFO: aptitude install..."
|
||||
aptitude install libapache2-mod-php5 php5-gd php-apc php5-mcrypt
|
||||
|
||||
git add .
|
||||
git commit -a -m "Installation Apache/PHP"
|
||||
|
||||
# Petite config. optimisée de php-apc
|
||||
if [ -f "/etc/php5/mods-available/apc.ini" ]; then
|
||||
echo "apc.rfc1867 = 1" >>/etc/php5/mods-available/apc.ini
|
||||
echo "apc.shm_size = 128M" >>/etc/php5/mods-available/apc.ini
|
||||
git commit -a -m "PHP/APC: configuration pour Drupal"
|
||||
fi
|
||||
|
||||
echo "INFO: modification du default vhost..."
|
||||
mkdir /var/www/default
|
||||
mv /var/www/index.html /var/www/default/
|
||||
patch_apache_default_vhost | git apply -
|
||||
git commit -a -m "Apache: default vhost dans sous-rep."
|
||||
|
||||
case "$TYPE_BDD" in
|
||||
'mysql')
|
||||
echo "INFO: aptitude install php5-mysql mysql-server ..."
|
||||
echo "NOTICE: laisser le mot de passe vide."
|
||||
aptitude install php5-mysql mysql-server
|
||||
git add .
|
||||
git commit -a -m "Install MySQL"
|
||||
|
||||
if [ -n "$BDD_CONNEXIONS_OPEN_BAR" ]; then
|
||||
patch_mysql_access_from_lan | git apply -
|
||||
git commit -a -m "MySQL: accès depuis le réseau"
|
||||
fi
|
||||
|
||||
# Génération d'un mot de passe aléatoire
|
||||
MYSQL_ADMIN_PASSWORD=$( dd if=/dev/random 2>/dev/null bs=1 count=10 status=noxfer | base64 | sed 's#[/=]##g' )
|
||||
echo "UPDATE mysql.user SET Password = PASSWORD('$MYSQL_ADMIN_PASSWORD') where User = 'root'" | mysql
|
||||
echo "FLUSH PRIVILEGES" | mysql
|
||||
|
||||
# mise en place de la sauvegarde
|
||||
printf "[client]\npassword=\"%s\"\n" "$MYSQL_ADMIN_PASSWORD" >~/.my_sauvegarde.cnf
|
||||
RANDOM_NUMBER=$( hexdump -n 2 -e '/2 "%u"' /dev/urandom )
|
||||
echo "$(( $RANDOM_NUMBER % 60 )) 10,16 * * 1-5 root test -x /root/sauvegarde_mysql.sh && /root/sauvegarde_mysql.sh --delete-olds" >>/etc/crontab
|
||||
git commit -a -m "cron: sauvegarde MySQL"
|
||||
;;
|
||||
|
||||
'postgresql')
|
||||
echo "INFO: aptitude install php5-pgsql postgresql-9.1 ..."
|
||||
aptitude install php5-pgsql postgresql-9.1
|
||||
git add .
|
||||
git commit -a -m "Install PostgreSQL"
|
||||
# mise en place de la sauvegarde
|
||||
RANDOM_NUMBER=$( hexdump -n 2 -e '/2 "%u"' /dev/urandom )
|
||||
echo "$(( $RANDOM_NUMBER % 60 )) 11,17 * * 1-5 root test -x /root/sauvegarde_postgresql.sh && /root/sauvegarde_postgresql.sh --delete-olds" >>/etc/crontab
|
||||
git commit -a -m "cron: sauvegarde PostgreSQL"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -z "$INSTALL_PHPBDDADMIN" ]; then
|
||||
case "$TYPE_BDD" in
|
||||
'mysql')
|
||||
echo "mdp root MySQL à copier : $MYSQL_ADMIN_PASSWORD"
|
||||
echo "appuyer sur entree pour continuer"
|
||||
read TOTO
|
||||
aptitude install phpmyadmin
|
||||
git add .
|
||||
git commit -a -m "Install phpmyadmin"
|
||||
|
||||
patch_phpmyadmin_access_from_lan | git apply -
|
||||
a2ensite phpmyadmin
|
||||
git add .
|
||||
git commit -a -m "PHPMyAdmin: vhost dédié"
|
||||
;;
|
||||
|
||||
'postgresql')
|
||||
aptitude install phppgadmin
|
||||
git add .
|
||||
git commit -a -m "Install phppgadmin"
|
||||
|
||||
# TODO vhost
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "INFO: a2enmod rewrite..."
|
||||
a2enmod rewrite
|
||||
git add .
|
||||
git commit -a -m "apache: activation mod-rewrite"
|
||||
|
||||
# création vhost site Drupal
|
||||
if [ ! -f "/etc/apache2/sites-available/$NOM_SITE" ]; then
|
||||
echo "INFO: Création du vhost..."
|
||||
cat <<EOF >/etc/apache2/sites-available/$NOM_SITE
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@localhost
|
||||
|
||||
ServerName $NOM_SITE
|
||||
#ServerAlias www
|
||||
#ServerAlias www.*
|
||||
|
||||
DocumentRoot /var/www/$NOM_SITE
|
||||
<Directory />
|
||||
Options None
|
||||
AllowOverride None
|
||||
deny from all
|
||||
</Directory>
|
||||
<Directory /var/www/$NOM_SITE/>
|
||||
Options FollowSymLinks
|
||||
AllowOverride All
|
||||
Order allow,deny
|
||||
allow from all
|
||||
</Directory>
|
||||
|
||||
ErrorLog \${APACHE_LOG_DIR}/${NOM_SITE}_error.log
|
||||
|
||||
# Possible values include: debug, info, notice, warn, error, crit,
|
||||
# alert, emerg.
|
||||
LogLevel warn
|
||||
|
||||
CustomLog \${APACHE_LOG_DIR}/${NOM_SITE}_access.log combined
|
||||
</VirtualHost>
|
||||
EOF
|
||||
mkdir /var/www/$NOM_SITE
|
||||
a2ensite $NOM_SITE
|
||||
apache2ctl configtest
|
||||
git add .
|
||||
git commit -a -m "apache: création vhost $NOM_SITE"
|
||||
else
|
||||
echo "WARNING: pas de création du vhost." >&2
|
||||
fi
|
||||
|
||||
if ! id "$NOM_UTILISATEUR" >/dev/null 2>&1; then
|
||||
echo "INFO: Création compte utilisateur..."
|
||||
adduser "$NOM_UTILISATEUR"
|
||||
usermod -a -G www-data "$NOM_UTILISATEUR"
|
||||
git commit -a -m "création utilisateur dédié pour déploiement/maintenance"
|
||||
else
|
||||
echo "WARNING: pas de création de l'utilisateur." >&2
|
||||
fi
|
||||
|
||||
if [ -d "/home/$NOM_UTILISATEUR" ] && [ -d "/var/www/$NOM_SITE" ] && id "$NOM_UTILISATEUR" >/dev/null 2>&1; then
|
||||
echo "INFO: on en profite pour mettre les droits spéciaux :)"
|
||||
chown $NOM_UTILISATEUR:www-data /var/www "/var/www/$NOM_SITE"
|
||||
chmod 2750 /var/www "/var/www/$NOM_SITE"
|
||||
echo "INFO: création lien symbolique..."
|
||||
su -c "ln -s '/var/www/$NOM_SITE' '/home/$NOM_UTILISATEUR/www-$NOM_SITE'" "$NOM_UTILISATEUR"
|
||||
else
|
||||
echo "WARNING: pas de création du lien symbolique dans le home de l'utilisateur." >&2
|
||||
fi
|
||||
|
||||
# Installation de Drush pour l'utilisateur dédié, si demandée
|
||||
if [ -n "$INSTALL_DRUSH" ]; then
|
||||
aptitude install php-pear
|
||||
git add .
|
||||
git commit -a -m "Installation de php-pear (pour Drush)"
|
||||
su -c 'pear config-create $HOME $HOME/.pearrc' "$NOM_UTILISATEUR"
|
||||
su -c "pear channel-discover pear.drush.org" "$NOM_UTILISATEUR"
|
||||
su -c "pear install drush/drush" "$NOM_UTILISATEUR"
|
||||
printf '\n# modification PATH pour drush\nPATH=$PATH:$HOME/pear\n' >>"$( getent passwd $NOM_UTILISATEUR | cut -d : -f 6)/.bashrc"
|
||||
fi
|
||||
|
||||
# Pré-remplissage du fichier /etc/exports
|
||||
cat <<EOF
|
||||
Ligne à ajouter à /etc/exports :
|
||||
/var/www/$NOM_SITE/sites/default/files 172.20.0.0/255.255.0.0(rw,insecure,all_squash,anonuid=33,anongid=33)
|
||||
EOF
|
||||
|
||||
cat <<EOF
|
||||
Ne pas oublier :
|
||||
- le serveur de mail,
|
||||
- la taille des uploads (post_max_size & upload_max_filesize)
|
||||
EOF
|
||||
|
||||
echo "The end."
|
200
oldies/script_suppression-utilisateur.sh
Executable file
200
oldies/script_suppression-utilisateur.sh
Executable file
|
@ -0,0 +1,200 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Ce script aide à la suppression d'un compte LDAP
|
||||
# Il s'occupe :
|
||||
# - suppression LDAP/SMB
|
||||
# - désabonnement aux listes d'emails (salaries@example.net, ...)
|
||||
# - destruction de la boîte Cyrus
|
||||
#
|
||||
# Ce script nécessite :
|
||||
# - des identifiants admin sur les listes emails (utilisation des identifiants smbldap pour l'instant. Pas glop.)
|
||||
# - des identifiants admin sur Cyrus. Ces identifiants seront contenus dans le fichier $CONFIG_IDENTIFIANTS_CYRUS, au format :
|
||||
# user=LOGIN
|
||||
# password=PASS
|
||||
#
|
||||
# TODO: meilleure détection quand l'email n'existe pas.
|
||||
|
||||
|
||||
# Config
|
||||
LDAP_HOST="ldap.example.net"
|
||||
LDAP_ROOT="dc=example,dc=net"
|
||||
CYRUS_HOST="messagerie.example.net"
|
||||
CONFIG_EMAIL_DOMAIN="example.net"
|
||||
CONFIG_IDENTIFIANTS_SMBLDAP="/etc/smbldap-tools/smbldap_bind.conf"
|
||||
CONFIG_IDENTIFIANTS_CYRUS="/root/.cyrus_auth"
|
||||
|
||||
# Initialisation des variables "globales"
|
||||
MODE_INTERACTIF="1"
|
||||
LOGFILE=$( mktemp )
|
||||
|
||||
|
||||
# Fonctions
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [-f] login
|
||||
$0 -h
|
||||
|
||||
-f : mode bourrin, ne pose pas de questions.
|
||||
EOF
|
||||
}
|
||||
|
||||
terminaison() {
|
||||
if [ "$1" = "" ] || [ "$1" -eq 0 ]; then
|
||||
rm -f "$LOGFILE"
|
||||
RETOUR=0
|
||||
else
|
||||
if [ -s "$LOGFILE" ]; then
|
||||
printf "NOTICE: log dispo : %s\n" "$LOGFILE" >&2
|
||||
else
|
||||
rm -f "$LOGFILE"
|
||||
fi
|
||||
RETOUR="$1"
|
||||
fi
|
||||
exit "$RETOUR"
|
||||
}
|
||||
|
||||
check_login() {
|
||||
# Vérifie que le login existe
|
||||
|
||||
# Si aucun argument fourni, exit
|
||||
test -n "$1" || return 1
|
||||
|
||||
# Vérification que le login (=uid LDAP) existe
|
||||
if [ $( ldapsearch -x -h "$LDAP_HOST" -b "ou=users,$LDAP_ROOT" -LLL "uid=$1" | grep -c "^dn: " ) -eq 0 ]; then
|
||||
echo "ERREUR: login inexistant." >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Enfin : le code...
|
||||
|
||||
# gestion des options de lancement
|
||||
while getopts fh f; do
|
||||
case $f in
|
||||
'f')
|
||||
MODE_INTERACTIF=0
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
terminaison 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
terminaison 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
LOGIN="$1"
|
||||
|
||||
|
||||
# Petite vérif.
|
||||
while ! check_login "$LOGIN"; do
|
||||
# En mode "bourrin", on gicle direct.
|
||||
if [ "$LOGIN" != "" ] && [ "$MODE_INTERACTIF" -eq 0 ]; then
|
||||
terminaison 1
|
||||
fi
|
||||
|
||||
# Sinon, on demande poliment
|
||||
printf "Login : "; read LOGIN
|
||||
done
|
||||
|
||||
|
||||
# Récupération de l'email
|
||||
RACINE_EMAIL=$( ldapsearch -x -h "$LDAP_HOST" -b "ou=users,$LDAP_ROOT" -LLL "(uid=$LOGIN)" mailLocalAddress | sed -n 's/^mailLocalAddress: //p' )
|
||||
|
||||
if [ "$RACINE_EMAIL" = "" ]; then
|
||||
echo "ERREUR: impossible de retrouver l'adresse e-mail." >&2
|
||||
terminaison 1
|
||||
fi
|
||||
|
||||
EMAIL="$RACINE_EMAIL@$CONFIG_EMAIL_DOMAIN"
|
||||
|
||||
# 1ere étape : Suppression du compte avec smbldap-userdel
|
||||
echo "Suppression du compte dans LDAP... (éviter le Ctrl-C à partir de maintenant)"
|
||||
if ! smbldap-userdel "$LOGIN"; then
|
||||
echo "ERREUR: smbldap-userdel a renvoyé une erreur. Arrêt du script $0." >&2
|
||||
return 1
|
||||
fi
|
||||
echo "Compte LDAP supprimé."
|
||||
echo
|
||||
|
||||
# 2ème étape : Suppression de l'adresse e-mail des mailing-lists
|
||||
printf "Suppression de l'e-mail %s de toutes les mailing-lists...\n" "$EMAIL"
|
||||
if ! ./script_ml-gestion-abonne.sh -r ALL "$EMAIL"; then
|
||||
cat <<EOF >&2
|
||||
NOTICE: apparemment, il y a eu un pépin à la gestion des mailing-lists.
|
||||
Le compte est supprimé, donc l'utilisateur ne peut plus consulter ses mails mais
|
||||
sa boîte peut néanmoins en recevoir.
|
||||
On on vous laisse vous débrouiller avec
|
||||
./script_ml-gestion-abonne.sh ou PHPLDAPAdmin.
|
||||
EOF
|
||||
fi
|
||||
echo
|
||||
|
||||
|
||||
# 3ème étape : suppression de la boîte mail dans Cyrus
|
||||
#
|
||||
# Tout se fait via un script Perl parce que les outils d'admin
|
||||
# de Cyrus sont pas franchement faciles à scripter...
|
||||
#
|
||||
# En mode non-bourrin, on demande une confirmation de la destruction.
|
||||
if [ "$MODE_INTERACTIF" -eq 1 ]; then
|
||||
printf "Supprimer la boîte mail dans Cyrus ? (O/n)"
|
||||
read TMP
|
||||
if [ -n "$TMP" ] && [ $( echo "$TMP" | egrep -ic "^o$" ) -eq 0 ]; then
|
||||
echo "Ah bon ?! Ben à la prochaine alors." >&2
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "Suppression de la boîte user.%s dans Cyrus.\n" "$RACINE_EMAIL"
|
||||
cat <<EOF | perl -MCyrus::IMAP::Admin
|
||||
# Connexion
|
||||
my \$conn = Cyrus::IMAP::Admin->new('$CYRUS_HOST') or die "Echec de connexion.";
|
||||
|
||||
# Lecture du fichier de configuration
|
||||
open CONFIG, '$CONFIG_IDENTIFIANTS_CYRUS';
|
||||
while (<CONFIG>) {
|
||||
chomp; # no newline
|
||||
s/^#.*//; # no comments
|
||||
s/^\s+//; # no leading white
|
||||
s/\s+$//; # no trailing white
|
||||
next unless length; # anything left?
|
||||
my (\$var, \$value) = split(/\s*=\s*/, \$_, 2);
|
||||
\$cyrus_config{\$var} = \$value;
|
||||
}
|
||||
|
||||
# Authentification
|
||||
\$conn->authenticate(
|
||||
"-user" => \$cyrus_config{'user'},
|
||||
"-password" => \$cyrus_config{'password'},
|
||||
"-mechanism" => 'LOGIN',
|
||||
) or die "Echec à l'authentification.";
|
||||
|
||||
# On se donne les droits pour supprimer la boîte mail
|
||||
\$conn->setacl('user.$RACINE_EMAIL',\$cyrus_config{'user'},"c") or die "Erreur dans la gestion des ACLs.";
|
||||
if ( \$conn->error ) {
|
||||
die "Erreur dans la gestion des ACLS.";
|
||||
}
|
||||
|
||||
# Destruction de la boîte
|
||||
\$conn->delete('user.$RACINE_EMAIL') or die "Erreur à la destruction de la boîte mail.";
|
||||
if ( \$conn->error ) {
|
||||
die "Erreur à la suppression de la boîte.";
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ "$?" -eq 0 ]; then
|
||||
echo "Boîte supprimée."
|
||||
else
|
||||
echo "ERREUR: erreur à la destruction de la boîte. C'était la dernière étape, voir avec Cyrus. Abandon." >&2
|
||||
return 1
|
||||
fi
|
||||
echo
|
||||
|
||||
echo "Fin du script."
|
94
oldies/script_synchro-externalisation-stats-dates-disques.sh
Executable file
94
oldies/script_synchro-externalisation-stats-dates-disques.sh
Executable file
|
@ -0,0 +1,94 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
# Ce script liste les derniers passages des disques
|
||||
# d'externalisation.
|
||||
# Selon les options fournies, il peut aussi mettre à
|
||||
# jour le listing.
|
||||
|
||||
# Config
|
||||
EXTERNAL_DISK_UUID="394165d5-b1dc-42a1-aa2e-006516f8e33f"
|
||||
DATABASE="/root/disques-externalisation_timestamp.lst"
|
||||
CORRESPONDANCE="/root/disques-externalisation_correspondance.lst"
|
||||
|
||||
|
||||
# Initialisation
|
||||
MISE_A_JOUR=0
|
||||
SILENCIEUX=0
|
||||
|
||||
|
||||
# affiche le message d'aide
|
||||
usage() {
|
||||
cat <<EOF
|
||||
$0 [ -u ] [ -U UUID ] [ -q ]
|
||||
$0 -h
|
||||
|
||||
-u : met à jour la BDD
|
||||
-U UUID : utilise cet UUID pour identifier la partition utilisée
|
||||
-q : silencieux, n'affiche pas le listing final
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# Début du code
|
||||
# gestion des options de lancement
|
||||
while getopts uU:h f; do
|
||||
case $f in
|
||||
'u')
|
||||
MISE_A_JOUR=1
|
||||
;;
|
||||
|
||||
'U')
|
||||
$EXTERNAL_DISK_UUID="$OPTARG"
|
||||
;;
|
||||
|
||||
'h')
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
\?)
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $( expr $OPTIND - 1 )
|
||||
|
||||
if [ "$MISE_A_JOUR" -gt 0 ]; then
|
||||
# On récupère l'id du disque
|
||||
# TODO : alerte si plusieurs devices correspondants ?
|
||||
if [ ! -e "/dev/disk/by-uuid/$EXTERNAL_DISK_UUID" ]; then
|
||||
exit 1
|
||||
fi
|
||||
DISQUE_ID=$( find /dev/disk/by-id -lname "$( readlink /dev/disk/by-uuid/$EXTERNAL_DISK_UUID )" | head -n 1 | xargs basename )
|
||||
|
||||
# ...et on l'ajoute au listing
|
||||
TMPFILE=$( mktemp )
|
||||
cat $DATABASE | grep -v "$DISQUE_ID" | grep -v "^$" >$TMPFILE
|
||||
printf "%d\t%s\n" "$( date +%s )" "$DISQUE_ID" >>$TMPFILE
|
||||
cat "$TMPFILE" | sort -n >$DATABASE
|
||||
rm -f "$TMPFILE"
|
||||
fi
|
||||
|
||||
if [ "$SILENCIEUX" -eq 0 ]; then
|
||||
TS_NOW=$( date +%s )
|
||||
# Listing avec nb de jours depuis dernière mise à jour
|
||||
printf " Age Label\n"
|
||||
cat "$DATABASE" | while read LINE; do
|
||||
TS=$( echo $LINE | awk '{ printf $1 }' )
|
||||
ID=$( echo $LINE | awk '{ printf $2 }' )
|
||||
LABEL=$( test -f "$CORRESPONDANCE" && cat "$CORRESPONDANCE" | sed -n "s/^$ID[[:space:]]\+\(.*\)$/\1/p" )
|
||||
|
||||
# Affichage du nombre de jours
|
||||
printf "%3dj " "$(( ( $TS_NOW - $TS ) / 86400 ))"
|
||||
|
||||
# Affichage du label de la table de correspondance (ou, si absent, de l'Id)
|
||||
if [ "$LABEL" == "" ]; then
|
||||
LABEL="$ID"
|
||||
fi
|
||||
printf "%s\n" "$LABEL"
|
||||
done
|
||||
fi
|
||||
|
||||
|
66
oldies/script_synchro-externalisation-wrapper.sh
Executable file
66
oldies/script_synchro-externalisation-wrapper.sh
Executable file
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
|
||||
LOGFILE=/var/log/externalisation.log
|
||||
DIR_SCRIPTS="/root/scripts-admin"
|
||||
ADRESSES_MAIL="supervision-externalisation@example.net"
|
||||
|
||||
$DIR_SCRIPTS/script_synchro-externalisation-from-serveur-sauvegarde.sh >$LOGFILE 2>&1
|
||||
|
||||
# Vérification de l'état de sortie
|
||||
case "$?" in
|
||||
0)
|
||||
( cat - <<EOF ; $DIR_SCRIPTS/script_synchro-externalisation-stats-dates-disques.sh -u ) | mail -s "[externalisation] Ok" -a "Content-Type: text/plain; charset=UTF-8" $ADRESSES_MAIL
|
||||
La synchro du disque d'externalisation s'est déroulée avec succès.
|
||||
|
||||
Le disque est à présent disponible.
|
||||
|
||||
-
|
||||
|
||||
Âge des dernières synchro par disque :
|
||||
EOF
|
||||
;;
|
||||
|
||||
1)
|
||||
( cat - <<EOF ; $DIR_SCRIPTS/script_synchro-externalisation-stats-dates-disques.sh ; printf "\n -\n"; tail "$LOGFILE" ) | mail -s "[externalisation] Erreur" -a "Content-Type: text/plain; charset=UTF-8" $ADRESSES_MAIL
|
||||
Erreur de synchronisation : le disque n'est pas disponible, intervention manuelle requise.
|
||||
|
||||
La synchronisation ne s'est pas déroulée normalement et le disque n'est pas disponible.
|
||||
10 dernières lignes du log ci-dessous pour plus d'information.
|
||||
Log dispo dans $LOGFILE
|
||||
|
||||
-
|
||||
|
||||
Âge des dernières synchro par disque :
|
||||
EOF
|
||||
;;
|
||||
|
||||
2)
|
||||
( cat - <<EOF ; $DIR_SCRIPTS/script_synchro-externalisation-stats-dates-disques.sh ; printf "\n -\n"; tail "$LOGFILE" ) | mail -s "[externalisation] Pas de disque" -a "Content-Type: text/plain; charset=UTF-8" $ADRESSES_MAIL
|
||||
10 dernières lignes du log ci-dessous pour plus d'information.
|
||||
Log dispo dans $LOGFILE
|
||||
|
||||
-
|
||||
|
||||
Âge des dernières synchro par disque :
|
||||
EOF
|
||||
;;
|
||||
|
||||
3)
|
||||
( cat - <<EOF ; $DIR_SCRIPTS/script_synchro-externalisation-stats-dates-disques.sh -u ; printf "\n -\n"; tail "$LOGFILE" ) | mail -s "[externalisation] Erreur post-synchro" -a "Content-Type: text/plain; charset=UTF-8" $ADRESSES_MAIL
|
||||
Le coeur de la synchro a bien été effectuée, mais le disque n'est néanmoins pas disponible.
|
||||
Intervention manuelle requise.
|
||||
|
||||
10 dernières lignes du log ci-dessous pour plus d'information.
|
||||
Log dispo dans $LOGFILE
|
||||
|
||||
-
|
||||
|
||||
Âge des dernières synchro par disque :
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Rotation des logs
|
||||
savelog -c 7 "$LOGFILE" >/dev/null
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue