From dcffa9ab5e6f696542df9e0c909e62c4935734e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Thu, 30 Nov 2017 21:10:24 +0100 Subject: [PATCH] add: archiving of container-journals Change-Id: Ifa920794c3b4dbc7cc619f5d6570b5d82505f200 --- backup | 18 ++++++++++++++ manager/backup | 64 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/backup b/backup index e1be93e..79e7478 100755 --- a/backup +++ b/backup @@ -103,6 +103,24 @@ EOF mkdir -p "/data/postgres/conf/${postgres_cluster}" printf "auto\n" > "/data/postgres/conf/${postgres_cluster}/start.conf" touch "/data/postgres/conf/${postgres_cluster}/postgresql.conf" + elif [[ $command == journal ]]; then + read -e from + action=$(date -u -d '00:00 today' +%s) + if [[ $action == $from ]]; then + printf "no journals\n" + continue + fi + printf "Until: %s\n" "$action" + for i in $(sudo lxc-ls); do + [[ $i == "base-image" ]] && continue + printf "journal: %s\n" "$i" + if [[ $from == - ]]; then + lxc-attach -n "$i" -- journalctl --utc --until="@$action" -o export | chunked + else + lxc-attach -n "$i" -- journalctl --utc --since="@$from" --until="@$action" -o export | chunked + fi + done + printf "end-of-journals\n" elif [[ $command == end ]]; then printf "end\n" fi diff --git a/manager/backup b/manager/backup index 22d536c..b707952 100755 --- a/manager/backup +++ b/manager/backup @@ -1,5 +1,4 @@ #!/bin/bash - targetHost=$1 targetHost=${targetHost%/} source config @@ -82,6 +81,64 @@ function incremental { printf "Done incremental backup\n" } +# This code snippet cannot be used inline and therefore has to be a function. +# When calling this function like 'receive_journal "journal" <&$fd', the +# file-descriptor "$fd" is resolved in the calling original shell. +# However when inlining this code like "... | ... <&$fd" the file-descriptor +# is resolved in the first subshell created by this command and therefore +# not valid anymore. +function receive_journal { + chunked decode | /lib/systemd/systemd-journal-remote -o "$1" - +} +function journal { + printf "Fetching journals...\n" + printf "journal\n" >&${COPROC[1]} + folder="$self" + for i in {1..10}; do + folder="$folder/prev" + if [[ -f "$folder/journal-until" ]]; then + break; + fi + done + if [[ -f "$folder/journal-until" ]]; then + printf "From: " + from="$(cat "$folder/journal-until")" + date --utc -d "@$from" + printf -- "%s\n" "$from" >&${COPROC[1]} + else + printf "From: start\n" + printf -- "-\n" >&${COPROC[1]} + fi + read -r until <&${COPROC[0]} || exit 1; + if [[ $until == "no journals" ]]; then + printf "no journal events\n" + return 1 + fi + if [[ ! $until == "Until: "* ]]; then + printf "Unexpected Until line: %s\n" "$until" + exit 1 + fi + until="${until#Until: }" + printf "until: " + date --utc -d "@$until" + + printf "Until: %s\n" "$until" + while :; do + read -r line <&${COPROC[0]} || exit 1; + if [[ $line == "end-of-journals" ]]; then + break; + fi + jnl="${line#journal: }" + printf "journal: %s\n" "$jnl" + receive_journal "$self/part-$jnl.journal" <&${COPROC[0]} + done + journalctl --file="$self/part-*" -o export | /lib/systemd/systemd-journal-remote -o "$self/all.journal" - + printf "Removing split journals:\n" + rm -v "$self/part-"*.journal + cat > "$self/journal-until" <<< "$until" + ls -als "$self" +} + if [[ "$2" == "restore" ]]; then sourceHost=$3 sourceHost=${sourceHost%/} @@ -126,8 +183,13 @@ if [[ "$2" == "restore" ]]; then fi printf "n\n" >&${COPROC[1]} elif [[ "$2" == "backup" ]]; then + if ! [[ -x /lib/systemd/systemd-journal-remote ]]; then + printf "This script requires 'systemd-journal-remote' to reformat received journals\n" + exit 1 + fi start_backup incremental + journal else printf "Error, unknown sub command: %s\n" "$2" >&2 fi -- 2.39.2