# This script is executed by "recovery_1st_stage" to recovery a Standby node.set-o xtrace # 参数1 - master节点PGDATA目录PRIMARY_NODE_PGDATA="$1"# 参数2 - 目的节点主机名或IPDEST_NODE_HOST="$2"# 参数3 - 目的节点PGDATA目录DEST_NODE_PGDATA="$3"# 参数4 - 主节点端口号PRIMARY_NODE_PORT="$4"# 参数5 - 目的节点ID(对应etc目录下的pgpool_node_id文件内容)DEST_NODE_ID="$5"# 参数6 - 目的节点端口号DEST_NODE_PORT="$6"# 参数7 - 主节点主机名或IPPRIMARY_NODE_HOST="$7"# pg安装目录PGHOME=/usr/local/pgsql16 # archive log目录ARCHIVEDIR=/data01/pgsql16/archive # 流复制用户名REPLUSER=replica # 复制槽名REPL_SLOT_NAME=${DEST_NODE_HOST//[-.]/_}# PostgreSQL数据库启动用户POSTGRESQL_STARTUP_USER=postgres # ssh免密登录密钥文件名SSH_KEY_FILE=id_rsa SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"echo recovery_1st_stage: start: pg_basebackup for Standby node$DEST_NODE_ID## 测试ssh免密登录ssh-T${SSH_OPTIONS}${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST}ls /tmp > /dev/null if [ $?-ne0 ]; thenecho recovery_1st_stage: passwordless SSH to ${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST} failed. Please setup passwordless SSH. exit1fi## 获取PostgreSQL主版本号PGVERSION=`${PGHOME}/bin/initdb -V | awk '{print $3}' | sed 's/\..*//' | sed 's/\([0-9]*\)[a-zA-Z].*/\1/'`if [ $PGVERSION-ge12 ]; thenRECOVERYCONF=${DEST_NODE_PGDATA}/myrecovery.conf elseRECOVERYCONF=${DEST_NODE_PGDATA}/recovery.conf fi## 创建复制槽 "${REPL_SLOT_NAME}"${PGHOME}/bin/psql -h${PRIMARY_NODE_HOST}-p${PRIMARY_NODE_PORT} postgres \ -c"SELECT pg_create_physical_replication_slot('${REPL_SLOT_NAME}');" >/dev/null 2>&1 if [ $?-ne0 ]; thenecho ERROR: recovery_1st_stage: create replication slot \"${REPL_SLOT_NAME}\" failed. You may need to create replication slot manually. fi## 执行pg_basebackup恢复从节点ssh-T${SSH_OPTIONS}${POSTGRESQL_STARTUP_USER}@$DEST_NODE_HOST" set -o errexit # 删除从节点PG_DATA目录 [ -d \"${DEST_NODE_PGDATA}\" ] && rm -rf ${DEST_NODE_PGDATA} # 删除从节点archive log目录 [ -d \"${ARCHIVEDIR}\" ] && rm -rf ${ARCHIVEDIR}/* # 执行pg_basebackup${PGHOME}/bin/pg_basebackup -h $PRIMARY_NODE_HOST -U $REPLUSER -p $PRIMARY_NODE_PORT -D $DEST_NODE_PGDATA -X stream # 创建从节点流复制配置文件 cat > ${RECOVERYCONF} << EOTprimary_conninfo = 'host=${PRIMARY_NODE_HOST} port=${PRIMARY_NODE_PORT} user=${REPLUSER} application_name=${DEST_NODE_HOST} passfile=''/home/postgres/.pgpass'''recovery_target_timeline = 'latest'restore_command = 'scp ${SSH_OPTIONS}${PRIMARY_NODE_HOST}:${ARCHIVEDIR}/%f %p'primary_slot_name = '${REPL_SLOT_NAME}'EOT # 修改postgresql.conf,加入加载流复制配置文件的设置 if [ ${PGVERSION} -ge 12 ]; then sed -i -e \"\\\$ainclude_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'\" \ -e \"/^include_if_exists = '$(echo ${RECOVERYCONF} | sed -e 's/\//\\\//g')'/d\" ${DEST_NODE_PGDATA}/postgresql.conf # 生成从节点标志文件 touch ${DEST_NODE_PGDATA}/standby.signal else echo \"standby_mode = 'on'\" >> ${RECOVERYCONF} fi sed -i \ -e \"s/#*port = .*/port = ${DEST_NODE_PORT}/\" \ -e \"s@#*archive_command = .*@archive_command = 'cp \\\"%p\\\" \\\"${ARCHIVEDIR}/%f\\\"'@\" \${DEST_NODE_PGDATA}/postgresql.conf"if [ $?-ne0 ]; then# 如果pg_basebackup失败,删除前面创建的复制槽${PGHOME}/bin/psql -h${PRIMARY_NODE_HOST}-p${PRIMARY_NODE_PORT} postgres \ -c"SELECT pg_drop_replication_slot('${REPL_SLOT_NAME}');" >/dev/null 2>&1 if [ $?-ne0 ]; thenecho ERROR: recovery_1st_stage: drop replication slot \"${REPL_SLOT_NAME}\" failed. You may need to drop replication slot manually. fiecho ERROR: recovery_1st_stage: end: pg_basebackup failed. online recovery failed exit1fiecho recovery_1st_stage: end: recovery_1st_stage is completed successfully exit0