3 ##This is meanst to be run on the slave, with the masters ip as the passed variable. ($1)
5 datadir=/var/lib/pgsql/9.6/data
6 archivedir=/var/lib/pgsql/9.6/archive
7 archivedirdest=/var/lib/pgsql/9.6/archive
9 cd # if used as root with sudo -u postgres home dir won't be readable and we will get errors
12 if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ];
14 echo "Usage: $0 masters ip address"
17 #This script must be run as postgres user
19 if [[ $(whoami) != "postgres" ]]
21 echo "[INFO] This script must be run as postgres user !"
26 #Check if postgres server is running on remote host
27 CheckIfPostgresIsRunningOnRemoteHost () {
28 is_active=$(systemctl --host $1 is-active postgresql-9.6)
30 if [ "$is_active" == "active" ]
32 echo "[OK] Postgres master running on remote host";
34 echo "[ERROR] Postgres not running on the master. Exiting..";
39 #Check if the supposed master is actually a master
40 CheckIfMasterIsActuallyAMaster () {
41 ismaster="$(ssh postgres@"$1" 'if [ -f /var/lib/pgsql/9.6/data/recovery.done ]; then echo "postgres_is_a_master_instance"; else echo "postgres_is_not_master"; fi;')"
43 if [[ "$ismaster" = "postgres_is_not_master" ]]
45 echo "[ERROR] Postgres is already running as a slave. Exiting..";
47 elif [[ "$ismaster" = "postgres_is_a_master_instance" ]]
49 echo "[INFO] Postgres is running as master (probably)";
50 elif echo "[ERROR] Unexpected response. Exiting.."
56 #prepare local server to become the new slave server.
57 PrepareLocalServer () {
59 if [ -f '/tmp/trigger_file' ]
63 echo "[INFO] Stopping slave node.."
64 #/usr/pgsql-9.6/bin/pg_ctl -D /var/lib/pgsql/9.6/data/ stop
65 sudo systemctl stop postgresql-9.6
67 if [[ -f "$datadir/recovery.done" ]];
69 mv "$datadir"/recovery.done "$datadir"/recovery.conf
73 rm -f /var/lib/pgsql/9.6/archive/*
77 CheckForRecoveryConfig () {
78 if [[ -f "$datadir/recovery.conf" ]];
80 echo "[OK] Slave config file found, Continuing.."
82 echo "[ERROR] recovery.conf not found. Postgres is not a slave. Exiting.."
88 #Put master into backup mode
89 #Before doing PutMasterIntoBackupMode clean up archive logs (IE rm or mv /var/lib/pgsql/9.6/archive/*). They are not needed since we are effectivly createing a new base backup and then synching it.
90 PutMasterIntoBackupMode () {
91 echo "[INFO] Putting postgres master '$1' in backup mode."
92 ssh postgres@"$1" "rm -f /var/lib/pgsql/9.6/archive/*"
93 ssh postgres@"$1" "psql -c \"SELECT pg_start_backup('Streaming Replication', true)\" postgres"
96 #rsync master's data to local postgres dir
98 echo "[INFO] Transfering data from master '$1' ..."
99 rsync -C -av --delete --progress -e ssh --exclude server.key --exclude server.crt --exclude recovery.conf --exclude recovery.done --exclude postmaster.pid --exclude pg_xlog/ "$1":"$datadir"/ "$datadir"/ > /dev/null
102 echo "[OK] Transfert completed.";
103 ln -sf $datadir/postgresql.conf.slave $datadir/postgresql.conf
105 echo "[ERROR] Error during transfer !";
111 #This archives the WAL log (ends writing to it and moves it to the $archive dir
112 StopBackupModeAndArchiveIntoWallLog () {
113 echo "[INFO] Disable backup mode from master '$1'."
114 ssh postgres@"$1" "psql -c \"SELECT pg_stop_backup()\" postgres"
115 echo "[INFO] Synchronising master/slave archive directory..."
116 rsync -C -a --progress -e ssh "$1":"$archivedir"/ "$archivedirdest"/ > /dev/null
119 echo "[OK] Sync achieved.";
121 echo "[ERROR] Error during sync !";
126 #stop postgres and copy transactions made during the last two rsync's
127 StopPostgreSqlAndFinishRsync () {
128 echo "[INFO] Stopping master node.."
129 ssh postgres@"$1" "sudo systemctl stop postgresql-9.6"
130 echo "[INFO] Transfering xlog files from master... "
131 rsync -av --delete --progress -e ssh "$sourcehost":"$datadir"/pg_xlog/ "$datadir"/pg_xlog/ > /dev/null
134 echo "[OK] Transfert completed.";
136 echo "[ERROR] Error during transfer !";
141 #Start both Master and Slave
142 StartLocalAndThenRemotePostGreSql () {
143 echo "[INFO] Starting slave node.."
144 sudo systemctl start postgresql-9.6
145 if ! systemctl -q is-active postgresql-9.6 ; then echo '[ERROR] Slave not running !'; else echo "[OK] Slave started."; fi;
148 echo "[INFO] Starting master node.."
149 ssh postgres@"$1" "sudo systemctl start postgresql-9.6"
151 status=$(systemctl --host $1 is-active postgresql-9.6)
152 if [ $status != "active" ]
154 echo "[ERROR] Master not running !";
157 echo "[OK] Master started.";
160 echo -n "[INFO] Wating for replication to start "
161 while [ "`psql -c 'SELECT * from pg_stat_replication' -h $1 -t postgres postgres | wc -l`" -lt 2 ] ; do
169 #Execute above operations
171 CheckIfPostgresIsRunningOnRemoteHost "$1"
172 CheckIfMasterIsActuallyAMaster "$1"
173 PrepareLocalServer "$datadir"
174 CheckForRecoveryConfig "$datadir"
175 PutMasterIntoBackupMode "$1"
177 StopBackupModeAndArchiveIntoWallLog "$1" "$archivedir" "$archivedirdest"
178 StopPostgreSqlAndFinishRsync "$1"
179 StartLocalAndThenRemotePostGreSql "$1"