#!/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