Last active
January 18, 2021 16:40
-
-
Save x-yuri/3d52b2e70dc84f4fc7eb177a5f204ac5 to your computer and use it in GitHub Desktop.
Barman scripts #pg #barman
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
. ~/lib/barman.sh | |
eval set -- "$( | |
getopt -o h --long n-base-backups:,n-standalone-base-backups:,dry-run,help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
p_n_base_backups= | |
p_n_standalone_base_backups= | |
p_dry_run= | |
while true; do | |
case "$1" in | |
--n-base-backups) p_n_base_backups=$2 | |
shift 2 | |
;; | |
--n-standalone-base-backups) p_n_standalone_base_backups=$2 | |
shift 2 | |
;; | |
--dry-run) p_dry_run=1 | |
shift | |
;; | |
-h|--help) cat <<USAGE | |
usage: $(basename -- "$0") [OPTIONS] SERVER | |
options: --n-base-backups N | |
--n-standalone-base-backups N | |
--dry-run | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
p_server=$1 | |
# target is either wal or standalone | |
backup_files() { | |
local b=$1 target=$2 | |
local f f2 files files2 | |
printf '%s\n' "$basebackups_directory/$b" | |
nlstr2arr "$(barman list-files --target "$target" -- "$p_server" "$b")" files | |
for f in "${files[@]}"; do | |
if starts_with "$f" "$basebackups_directory"; then # standalone | |
continue | |
fi | |
ls -1 -- "$f"* | |
done | |
} | |
# get list of backups | |
nlstr2arr "$(barman list-backup --minimal -- "$p_server")" backups | |
# exit if no backups to be deleted | |
if (( ${#backups[@]} <= p_n_base_backups )); then | |
exit | |
fi | |
basebackups_directory=$(get_server_var "$p_server" basebackups_directory) | |
wals_directory=$(get_server_var "$p_server" wals_directory) | |
# what to keep | |
nlstr2arr "$( | |
set -eu | |
{ | |
for (( i = 0; i < p_n_base_backups; i++ )); do | |
backup_files "${backups[$i]}" wal | |
done | |
for (( i = p_n_base_backups; | |
i < p_n_base_backups + p_n_standalone_base_backups | |
&& i < ${#backups[@]}; | |
i++ )); do | |
backup_files "${backups[$i]}" standalone | |
done | |
} | sort | uniq # the first bunch have common WAL files | |
)" keep_files | |
# which backups to delete | |
nlstr2arr "$(ls -d -- "$basebackups_directory"/*)" all_base_backups | |
delete_base_backups=() | |
for f in "${all_base_backups[@]}"; do | |
if ! in_array "$f" "${keep_files[@]}"; then | |
delete_base_backups+=("$f") | |
fi | |
done | |
# which WALs to delete | |
nlstr2arr "$(ls -- "$wals_directory"/*/*)" all_wals | |
delete_wals=() | |
for f in "${all_wals[@]}"; do | |
if ! in_array "$f" "${keep_files[@]}"; then | |
delete_wals+=("$f") | |
fi | |
done | |
# delete | |
for f in "${delete_base_backups[@]}"; do | |
cmd=(rm -rf -- "$f") | |
if (( p_dry_run )); then | |
printf '%s\n' "${cmd[*]}" | |
else | |
"${cmd[@]}" | |
fi | |
done | |
for f in "${delete_wals[@]}"; do | |
cmd=(rm -- "$f") | |
if (( p_dry_run )); then | |
printf '%s\n' "${cmd[*]}" | |
else | |
"${cmd[@]}" | |
fi | |
done | |
barman rebuild-xlogdb -- "$p_server" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
eval set -- "$( | |
getopt -o h --long help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
while true; do | |
case "$1" in | |
-h|--help) cat <<USAGE | |
usage: $(basename -- "$0") SERVER | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
p_server=$1 | |
re='^(\s*streaming_archiver\s*=\s*)\S+(.*)' | |
sed -Ei -- 's/'"$re"'/# &/' /etc/barman.d/"$p_server".conf |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
eval set -- "$( | |
getopt -o h --long help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
while true; do | |
case "$1" in | |
-h|--help) cat <<USAGE | |
usage: $(basename -- "$0") SERVER | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
p_server=$1 | |
f=/etc/barman.d/"$p_server".conf | |
re='^(\s*streaming_archiver\s*=\s*)\S+(.*)' | |
if egrep -q -- "$re" "$f"; then | |
sed -Ei -- 's/'"$re"'/\1on\2/' "$f" | |
else | |
re='^\s*#\s?'${re:1} | |
egrep -q -- "$re" "$f" \ | |
&& sed -Ei -- 's/'"$re"'/\1on\2/' "$f" \ | |
|| printf 'streaming_archiver = on\n' >> "$f" | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
. ~/.barman-vars | |
. ~/lib/barman.sh | |
eval set -- "$( | |
getopt -o h --long target-immediate,restore-standby,standby-host:,standby-port:,help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
p_target_immediate= | |
p_restore_standby= | |
p_standby_host= | |
p_standby_port=22 | |
while true; do | |
case "$1" in | |
--target-immediate) p_target_immediate=1 | |
shift | |
;; | |
--restore-standby) p_restore_standby=1 | |
shift | |
;; | |
--standby-host) p_standby_host=$2 | |
shift 2 | |
;; | |
--standby-port) p_standby_port=$2 | |
shift 2 | |
;; | |
-h|--help) cat <<USAGE | |
restore db, then standby | |
usage: $(basename -- "$0") [OPTIONS] SERVER BACKUP | |
options: --target-immediate | |
--restore-standby | |
--standby-host HOST | |
--standby-port PORT | |
Restoring standby is performed if --standby-host was specified. --restore-standby makes it skip restoring db. | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
p_server=$1 | |
p_backup_id=$2 | |
if [ "$p_restore_standby" ]; then | |
host=$p_standby_host | |
port=$p_standby_port | |
else | |
host=$p_server | |
port=${barman_server_port[$p_server]} | |
fi | |
if [ "$p_target_immediate" ] && [ "$p_restore_standby" ]; then | |
printf '%s: --target-immediate and --restore-standby are mutually exclusive\n' >&2 | |
exit 1 | |
fi | |
pg_home=${barman_server_home[$p_server]} | |
datadir=${barman_server_data_directory[$p_server]} | |
datadir_rel=${datadir:$(( ${#pg_home} + 1 ))} | |
verdir=$pg_home/${datadir_rel%%/*} | |
ssh -p "$port" -- "$host" "pg_home=${pg_home@Q} verdir=${verdir@Q} host=${host@Q} bash -lc ' | |
set -eu | |
timestamp=\$(date +%Y%m%d-%H%M%S) | |
printf \"%s %s: stop pg\\\\n\" -- \"\$host\" | |
pg-stop.sh | |
# move data dir | |
if [ -e \"\$verdir\" ]; then | |
printf \"%s %s: move data dir\\\\n\" -- \"\$host\" | |
su - -c \"mv \${verdir@Q}{,-\${timestamp@Q}}\" -- postgres | |
fi | |
'" | |
if ! [ "$p_restore_standby" ]; then | |
printf "%s %s: stop streaming\\n" -- "$p_server" | |
barman-disable-streaming.sh -- "$p_server" | |
barman-stop-streaming.sh -- "$p_server" | |
fi | |
# enable get-wal | |
recovery_options_re='^(\s*recovery_options\s*=\s*)\S+(.*)' | |
disable_get_wal() { | |
sed -Ei -- '/'"$recovery_options_re"'/d' "/etc/barman.d/$p_server.conf" | |
} | |
if [ "$p_restore_standby" ]; then | |
printf "%s %s: enable get-wal\\n" -- "$p_server" | |
disable_get_wal | |
printf 'recovery_options = get-wal\n' >> "/etc/barman.d/$p_server.conf" | |
trap disable_get_wal EXIT | |
fi | |
# recover | |
printf "%s %s: recover\\n" -- "$host" | |
args=() | |
if (( p_target_immediate )); then | |
args+=(--target-immediate --target-action promote) | |
fi | |
if [ "$p_restore_standby" ]; then | |
args+=(--standby-mode) | |
fi | |
barman recover "${args[@]}" \ | |
--remote-ssh-command "ssh -p ${port@Q} postgres@${host@Q}" \ | |
-- "$p_server" "$p_backup_id" "${barman_server_data_directory[$p_server]}" | |
# disable get-wal | |
if [ "$p_restore_standby" ]; then | |
printf "%s %s: disable get-wal\\n" -- "$p_server" | |
disable_get_wal | |
fi | |
# copy partial wal file | |
if ! (( p_target_immediate )) \ | |
&& ! [ "$p_restore_standby" ] \ | |
&& [ -e /var/lib/barman/"$p_server"/streaming/*.partial ]; then | |
printf "%s %s: copy partial wal\\n" -- "$p_server" | |
f=$(basename -- /var/lib/barman/$p_server/streaming/*.partial .partial) | |
su - -c " | |
scp -P ${port@Q} -- /var/lib/barman/${p_server@Q}/streaming/*.partial \\ | |
postgres@${host@Q}:${barman_server_data_directory[$p_server]@Q}/pg_wal/${f@Q} | |
" -- barman | |
fi | |
if [ "$p_restore_standby" ]; then | |
ssh -p "$port" -- "$host" " | |
standby_datadir=${barman_server_data_directory[$host]@Q} | |
# fix recovery.conf | |
printf \"%s %s: fix recovery.conf\\\\n\" -- ${host@Q} | |
sed -Ei 's/(barman-wal-restore\\s+-U\\s+\\w+\\s+)(\\w+)/\\1barman-wal-restore-\\2/' \\ | |
\"\$standby_datadir/recovery.conf\" | |
# start pg | |
printf \"%s %s: start pg\\\\n\" -- ${host@Q} | |
systemctl start postgresql | |
" | |
else | |
if [ "$p_target_immediate" ]; then | |
printf "%s %s: stop streaming\\n" -- "$p_server" | |
barman-disable-streaming.sh -- "$p_server" | |
barman-stop-streaming.sh -- "$p_server" | |
printf "%s %s: move barman server dir\\n" -- "$p_server" | |
mv -- /var/lib/barman/"$p_server"{,-$(date +%Y%m%d-%H%M%S)} | |
fi | |
printf "%s %s: start pg\\n" -- "$p_server" | |
ssh -p "$port" -- "$host" ' | |
set -eu | |
pg_home='"${pg_home@Q}"' | |
datadir='"${datadir@Q}"' | |
step=$(printf "1 * 5\\n" | bc) | |
start=$(date +%s) | |
printf "[%s] start\\n" "$(date -d @$start)" | |
systemctl start postgresql | |
IFS=: read -r today now <<< $(date +%F:%s) | |
midnight=$(date -d "$today 0" +%s) | |
t=$(( midnight + (now - midnight) * step / step )) | |
while true; do | |
(( t += step )) | |
sleep $(( t - $(date +%s) )) | |
in_recovery=$(su - -c "psql -Atc \"select pg_is_in_recovery()\"" -- postgres \ | |
|| printf "t\\n") | |
if [ "$in_recovery" != t ]; then | |
break | |
fi | |
wal=$(ps -u postgres -o pid,comm,args | grep "startup process" | awk "{print \$NF}") | |
last_wal=$(find "$datadir"/pg_wal -mindepth 1 -maxdepth 1 -type f -printf "%f\\n" \ | |
| sort \ | |
| tail -n 1) | |
recovery_conf=$(basename -- "$(ls -- "$datadir"/recovery*)") | |
printf "\\r[%s] %s %s %s/%s" \ | |
"$(date "+%F %T")" \ | |
"$in_recovery" \ | |
"$recovery_conf" \ | |
"$wal" \ | |
"$last_wal" | |
done | |
end=$(date +%s) | |
printf "[%s] end\\n" "$(date -d @$end)" | |
' | |
printf "%s %s: create replication slot\\n" -- "$p_server" | |
barman receive-wal --create-slot -- "$p_server" || true # create replication slot | |
printf "%s %s: start streaming\\n" -- "$p_server" | |
barman-enable-streaming.sh -- "$p_server" | |
barman-start-streaming.sh | |
if [ "$p_target_immediate" ]; then | |
printf "%s %s: create directory structure\\n" -- "$p_server" | |
barman check -- "$p_server" &> /dev/null || true # create directory structure | |
printf "%s %s: switch wal\\n" -- "$p_server" | |
barman switch-wal --force --archive -- "$p_server" # switch WAL file | |
printf "%s %s: backup\\n" -- "$p_server" | |
barman backup -- "$p_server" | |
fi | |
if [ "$p_standby_host" ]; then | |
printf "%s %s: recreate standby\\n" -- "$p_server" | |
"$0" --restore-standby --standby-host "$p_standby_host" --standby-port "$p_standby_port" \ | |
-- "$p_server" "$p_backup_id" | |
fi | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
eval set -- "$( | |
getopt -o h --long help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
while true; do | |
case "$1" in | |
-h|--help) cat <<USAGE | |
usage: $(basename -- "$0") | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
barman cron |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
eval set -- "$( | |
getopt -o h --long help \ | |
-n "$(basename -- "$0")" -- "$@" | |
)" | |
while true; do | |
case "$1" in | |
-h|--help) cat <<USAGE | |
usage: $(basename -- "$0") SERVER | |
USAGE | |
exit | |
;; | |
--) shift | |
break | |
;; | |
esac | |
done | |
p_server=$1 | |
barman receive-wal --stop -- "$p_server" || true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# quote for ERE | |
qe() { | |
local s=$1 delimiter=${2:-} | |
local re='\.|\*|\[|\^|\$|\\|\+|\?|\{|\||\(' # .*[^$\+?{|( | |
if [ "$delimiter" ]; then | |
re=$re'|\'$delimiter | |
fi | |
printf '%s\n' "$s" | sed -E -- 's/('"$re"')/\\\1/g' | |
} | |
nlstr2arr() { | |
local __IFS __el __r __s=$1 __a=$2 | |
__IFS=$IFS | |
IFS=$'\n' | |
__r=($__s) | |
IFS=$__IFS | |
eval "$__a=()" | |
for __el in "${__r[@]}"; do | |
eval "$__a+=(${__el@Q})" | |
done | |
} | |
in_array() { | |
local el=$1 | |
shift | |
local a=("$@") | |
for el2 in "${a[@]}"; do | |
if [ "$el2" = "$el" ]; then | |
return 0 | |
fi | |
done | |
return 1 | |
} | |
starts_with() { | |
local s=$1 prefix=$2 | |
[[ "$s" == "$prefix"* ]] | |
} | |
get_server_var() { | |
local srv=$1 var=$2 | |
local q_var=$(qe "$var") | |
barman show-server -- "$srv" \ | |
| egrep -- "^\s*$q_var\s*:" \ | |
| sed -E -- 's/^[^:]+:\s*//' | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -eu | |
services=$(systemctl list-units 'postgresql*' \ | |
| grep ^postgresql \ | |
| awk '{print $1}') | |
main_pids() { | |
printf '%s' "$services" \ | |
| xargs -rI{} -d'\n' systemctl show -p MainPID {} \ | |
| sed -E 's/.*=//' | |
} | |
systemctl stop postgresql | |
while [ "$(main_pids | tr -d '\n' | sed -E 's/0//g')" ]; do :; done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment