]> WPIA git - infra.git/blob - manager/backup
add: backup mechanism for postgresql
[infra.git] / manager / backup
1 #!/bin/bash
2
3 targetHost=$1
4 targetHost=${targetHost%/}
5 source config
6 source "$targetHost/config"
7
8 if ! which chunked >/dev/null; then
9     printf "Requires 'chunked' package from deb2.dogcraft.de\n" >&2
10     exit 1
11 fi
12
13
14
15 backup_target="$targetHost/backups"
16 coproc {
17     ssh_target "sudo ./backup"
18     read -r end
19 }
20 read -r line <&${COPROC[0]} || exit 1;
21 if [[ $line != "Backup service ready" ]]; then
22     echo "Backup service did not respond"
23     exit 1
24 fi
25 function start_backup {
26     ident="$(date "+%Y-%m-%d-%H-%M-%S")"
27     self="$backup_target/$ident"
28     mkdir -p "$self"
29     if [[ -h "$backup_target/last" ]]; then
30         last="$(readlink "$backup_target/last")"
31         ln -s "../$last" "$self/prev"
32         rm "$backup_target/last"
33     fi
34     ln -s "$ident" "$backup_target/last"
35 }
36 function base {
37     printf "base\n" >&${COPROC[1]}
38     chunked decode <&${COPROC[0]} > "$self/pg_base.tar.gz"
39     ls -alsh -- "$self/pg_base.tar.gz"
40     read -r line <&${COPROC[0]} || exit 1;
41     echo "pg_base done: $line"
42     echo "Backup info: "
43     tar xzO backup_label <  "$self/pg_base.tar.gz"
44 }
45 function incremental {
46     last=
47     hash=
48     if [[ $(find -L "$self" -maxdepth 14 -name "pg_base.tar.gz" | wc -l) -lt 1 ]]; then
49         printf "doing pg_base backup to $self/pg_base.tar.gz:\n"
50         base
51         last="$(tar xzO backup_label <  "$self/pg_base.tar.gz" | grep "^START WAL LOCATION: " | sed "s/.*(file \\(.*\\))/\\1/")"
52         hash="-"
53     else
54         last=""
55         folder="$self"
56         while [[ $last == "" ]]; do
57             folder="$folder/prev"
58             last="$(tar tf "$folder/pg_wal.tar.gz" | grep "^[A-Z0-9]*$" | tail -n 1)"
59         done
60         echo "Found last WAL file in backup: $folder"
61         hash=$(tar xfO "$folder/pg_wal.tar.gz" "$last" | sha256sum | cut -d" " -f1)
62     fi
63     printf "Last WAL-name: %s\n" "$last"
64     printf "incremental\n" >&${COPROC[1]}
65     printf "%s\n" "$last" >&${COPROC[1]}
66     printf "%s\n" "$hash" >&${COPROC[1]}
67     read -r line <&${COPROC[0]} || exit 1;
68     if [[ "$line" != "Ready" ]]; then
69         printf "incremental backup didn't start\n"
70         exit 1
71     fi
72     chunked decode <&${COPROC[0]} > "$self/pg_wal.tar.gz"
73     printf "Tar contents\n"
74     tar tf "$self/pg_wal.tar.gz"
75     ls -alsh -- "$self/pg_wal.tar.gz"
76     read -r line <&${COPROC[0]} || exit 1;
77     if [[ $line == "incremental backup done, confirm cleanup!" ]]; then
78         printf "y\n" >&${COPROC[1]}
79     else
80         printf "Done, but got strange line for cleanup confirmation: %s\n" "$line"
81     fi
82     printf "Done incremental backup\n"
83 }
84
85 if [[ "$2" == "restore" ]]; then
86     sourceHost=$3
87     sourceHost=${sourceHost%/}
88     backup_target="${sourceHost}/backups"
89     folder="$backup_target/last"
90     printf "Restoring backup %s\n" "$(readlink -e -- "$folder")"
91     tar tf "$folder/pg_wal.tar.gz"
92     while ! [[ -f "$folder/pg_base.tar.gz" ]]; do
93         folder="$folder/prev"
94         printf "Requires backup %s\n" "$(readlink -e -- "$folder")"
95         tar tf "$folder/pg_wal.tar.gz"
96     done
97     #tar tf "$folder/pg_base.tar.gz"
98     printf "restore\n" >&${COPROC[1]}
99     read -r reply <&${COPROC[0]} || exit 1;
100     if [[ $reply != "postgres base" ]]; then
101         printf "Service is not ready to receive backup: %s\n" "$reply"
102         exit 1
103     fi
104     echo "sending base"
105     chunked < "$folder/pg_base.tar.gz" >&${COPROC[1]}
106     echo "done sending base"
107     folder="$backup_target/last"
108     while :; do
109         read -r reply <&${COPROC[0]} || exit 1;
110         if [[ $reply != "incremental?" ]]; then
111             printf "Service is not ready to receive backup: %s\n" "$reply"
112             exit 1
113         fi
114         printf "y\n" >&${COPROC[1]}
115         printf "Sending pg_wal from %s\n" "$(readlink -e -- "$folder")"
116         chunked < "$folder/pg_wal.tar.gz" >&${COPROC[1]}
117         if [[ -f "$folder/pg_base.tar.gz" ]]; then
118             break
119         fi
120         folder="$folder/prev"
121     done
122     read -r reply <&${COPROC[0]} || exit 1;
123     if [[ $reply != "incremental?" ]]; then
124         printf "Service is not ready to receive backup: %s\n" "$reply"
125         exit 1
126     fi
127     printf "n\n" >&${COPROC[1]}
128 elif [[ "$2" == "backup" ]]; then
129     start_backup
130     incremental
131 else
132     printf "Error, unknown sub command: %s\n" "$2" >&2
133 fi
134
135
136 printf "end\n" >&${COPROC[1]}
137 read -r line <&${COPROC[0]} || exit 1;
138 printf "END: %s\n" "$line"