3 ##This is meanst to be run on the slave, with the masters ip as the passed variable. ($1)
5 datadir=/var/lib/postgresql/9.1/main
6 archivedir=/var/lib/postgresql/9.1/archive
7 archivedirdest=/var/lib/postgresql/9.1/archive
10 if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ];
12 echo "Usage: $0 masters ip address"
15 #This script must be run as postgres user
17 if [[ $(whoami) != "postgres" ]]
19 echo "[INFO] This script must be run as postgres user !"
24 #Check if postgres server is running on remote host
25 CheckIfPostgresIsRunningOnRemoteHost () {
26 isrunning="$(ssh postgres@"$1" 'if killall -0 postgres; then echo "postgres_running"; else echo "postgress_not_running"; fi;')"
28 if [[ "$isrunning" = "postgress_not_running" ]]
30 echo "[ERROR] Postgres not running on the master. Exiting..";
33 elif [[ "$isrunning" = "postgres_running" ]]
35 echo "[OK] Postgres master running on remote host";
37 elif echo "[ERROR] Unexpected response. Exiting.."
43 #Check if the supposed master is actually a master
44 CheckIfMasterIsActuallyAMaster () {
45 ismaster="$(ssh postgres@"$1" 'if [ -f /var/lib/postgresql/9.1/main/recovery.done ]; then echo "postgres_is_a_master_instance"; else echo "postgres_is_not_master"; fi;')"
47 if [[ "$ismaster" = "postgres_is_not_master" ]]
49 echo "[ERROR] Postgres is already running as a slave. Exiting..";
51 elif [[ "$ismaster" = "postgres_is_a_master_instance" ]]
53 echo "[INFO] Postgres is running as master (probably)";
54 elif echo "[ERROR] Unexpected response. Exiting.."
60 #prepare local server to become the new slave server.
61 PrepareLocalServer () {
63 if [ -f '/tmp/trigger_file' ]
67 echo "[INFO] Stopping slave node.."
68 bash /etc/init.d/postgresql stop
70 if [[ -f "$datadir/recovery.done" ]];
72 mv "$datadir"/recovery.done "$datadir"/recovery.conf
76 rm /var/lib/postgresql/9.1/archive/*
80 CheckForRecoveryConfig () {
81 if [[ -f "$datadir/recovery.conf" ]];
83 echo "[OK] Slave config file found, Continuing.."
85 echo "[ERROR] recovery.conf not found. Postgres is not a slave. Exiting.."
91 #Put master into backup mode
92 #Before doing PutMasterIntoBackupMode clean up archive logs (IE rm or mv /var/lib/postgresql/9.1/archive/*). They are not needed since we are effectivly createing a new base backup and then synching it.
93 PutMasterIntoBackupMode () {
94 echo "[INFO] Putting postgres master '$1' in backup mode."
95 ssh postgres@"$1" "rm /var/lib/postgresql/9.1/archive/*"
96 ssh postgres@"$1" "psql -c \"SELECT pg_start_backup('Streaming Replication', true)\" postgres"
99 #rsync master's data to local postgres dir
101 echo "[INFO] Transfering data from master '$1' ..."
102 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
105 echo "[OK] Transfert completed.";
107 echo "[ERROR] Error during transfer !";
113 #This archives the WAL log (ends writing to it and moves it to the $archive dir
114 StopBackupModeAndArchiveIntoWallLog () {
115 echo "[INFO] Disable backup mode from master '$1'."
116 ssh postgres@"$1" "psql -c \"SELECT pg_stop_backup()\" postgres"
117 echo "[INFO] Synchronising master/slave archive directory..."
118 rsync -C -a --progress -e ssh "$1":"$archivedir"/ "$archivedirdest"/ > /dev/null
121 echo "[OK] Sync achieved.";
123 echo "[ERROR] Error during sync !";
128 #stop postgres and copy transactions made during the last two rsync's
129 StopPostgreSqlAndFinishRsync () {
130 echo "[INFO] Stopping master node.."
131 ssh postgres@"$1" "/etc/init.d/postgresql stop"
132 echo "[INFO] Transfering xlog files from master... "
133 rsync -av --delete --progress -e ssh "$sourcehost":"$datadir"/pg_xlog/ "$datadir"/pg_xlog/ > /dev/null
136 echo "[OK] Transfert completed.";
138 echo "[ERROR] Error during transfer !";
143 #Start both Master and Slave
144 StartLocalAndThenRemotePostGreSql () {
145 echo "[INFO] Starting slave node.."
146 /etc/init.d/postgresql start
147 if ! killall -0 postgres; then echo '[ERROR] Slave not running !'; else echo "[OK] Slave started."; fi;
150 echo "[INFO] Starting master node.."
151 ssh postgres@"$1" "/etc/init.d/postgresql start"
153 status=$(ssh postgres@$1 "if ! killall -0 postgres; then echo 'error'; else echo 'running'; fi;")
154 if [ $status == "error" ]
156 echo "[ERROR] Master not running !";
159 echo "[OK] Master started.";
163 #Execute above operations
165 CheckIfPostgresIsRunningOnRemoteHost "$1"
166 CheckIfMasterIsActuallyAMaster "$1"
167 PrepareLocalServer "$datadir"
168 CheckForRecoveryConfig "$datadir"
169 PutMasterIntoBackupMode "$1"
171 StopBackupModeAndArchiveIntoWallLog "$1" "$archivedir" "$archivedirdest"
172 StopPostgreSqlAndFinishRsync "$1"
173 StartLocalAndThenRemotePostGreSql "$1"