diff --git a/CHANGELOG.md b/CHANGELOG.md index 071f938..bceb0ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Print promtail-friendly logs. See [#37](https://github.com/coopdevs/backups_role/pull/37) + ## [v1.2.4] - 2019-12-03 ### Fixed diff --git a/templates/cron-main.sh.j2 b/templates/cron-main.sh.j2 index 4971d22..43764a0 100644 --- a/templates/cron-main.sh.j2 +++ b/templates/cron-main.sh.j2 @@ -3,22 +3,11 @@ # Exit with error code 1 if any command fails set -e -# Clone standard output to standard error -#+ This way we have titles and datetimes in both outputs: err and out -#+ and therefore error messages appear within a context. -#+ In Linux this is equivalent to /dev/std{out,err} -#+ that sounds more intuitive, but it's not as portable. -#+ See https://unix.stackexchange.com/a/123659 - -# Use `tee -a` to append error logs instead of overwritting -# It is interpreted before the later append stderr redirection `2>>` -#+ Example: -#+ for i in 1 2 3; do { date | tee /dev/fd/2; } >> out.log 2>> err.log ; done -#+ err.log has only one line, while out.log has three. - -function title { - echo -e "\n## $1 ##" | tee -a /dev/fd/2; - date | tee -a /dev/fd/2; +# Output to stdout the message given, escaping its newlines and prefixing with date and loglevel +function log { + LOGLEVEL=${LOGLEVEL:-INFO} + ARGS="$@" + echo "$(date --rfc-3339=ns) | $LOGLEVEL | ${ARGS//$'\n'/\\n}" } # Remove temporal directory @@ -26,13 +15,27 @@ function clean { rm -rf "{{ backups_role_tmp_path }}" } +# Runner that saves stderr and logs it if command fails +function run { + + set +e + ERR_S=$(eval "$@" 2>&1 1>/dev/null) + ERR_C=$? + set -e + + if [ $ERR_C -ne 0 ]; then + export LOGLEVEL="ERROR" + log "$ERR_S" + exit $ERR_C + fi +} + # Set up an exit trap to delete temporal directory #+ before exiting, even if there are errors. trap clean EXIT -title "Create temporal directory" -mkdir -p "{{ backups_role_tmp_path }}" -echo "…done" +log "Create temporal directory" +run mkdir -p "{{ backups_role_tmp_path }}" # Execute scripts in chain if error code is ok {# Append and render script template to prepare backup #} @@ -40,3 +43,5 @@ echo "…done" {# Append and render script template to upload backup #} {% include "cron-upload.sh.j2" %} + +log "Backup complete" diff --git a/templates/cron-prepare.sh.j2 b/templates/cron-prepare.sh.j2 index a9e5b24..5a42d17 100644 --- a/templates/cron-prepare.sh.j2 +++ b/templates/cron-prepare.sh.j2 @@ -1,11 +1,6 @@ {# This template is included by cron-main.sh.j2 #} -# NOTE -# This script is meant to be executed by a very limited sudoer user. -# It must be allowed to only execute `tar -czvf *` as root, -# meaning that it can't uncompress, add options, or even change the options order. -# This is a way to give to this user read-only access to whole filesystem. -title "Postgres DB dump" +log "Postgres DB dump" {# jinja comment. Next non-comment line below should render to something like: for DB in "main" "secondary" "test"; do @@ -18,10 +13,13 @@ title "Postgres DB dump" https://stackoverflow.com/a/49692186/3625897 #} for DB in "{{ backups_role_db_names | join('" "') }}"; do - /usr/bin/pg_dump --encoding=UTF8 "$DB" > "{{ backups_role_tmp_path }}/pg_dump_$DB" + run /usr/bin/pg_dump --encoding=UTF8 "$DB" > "{{ backups_role_tmp_path }}/pg_dump_$DB" done -echo "…done" -title "Compress assets data" -sudo tar -czvf {{ backups_role_tmp_path }}/assets.tar.gz {{ backups_role_assets_paths|join(' ') }} -echo "…done" +# This command below is meant to be executed by a very limited sudoer user. +# It must be allowed to only execute `tar -czvf *` as root, +# meaning that it can't uncompress, add options, or even change the options order. +# This is a way to give to this user read-only access to whole filesystem. + +log "Compress assets data" +run sudo tar -czvf {{ backups_role_tmp_path }}/assets.tar.gz {{ backups_role_assets_paths|join(' ') }} diff --git a/templates/cron-upload.sh.j2 b/templates/cron-upload.sh.j2 index 607072b..0017e49 100644 --- a/templates/cron-upload.sh.j2 +++ b/templates/cron-upload.sh.j2 @@ -1,6 +1,7 @@ {# This template is included by cron-main.sh.j2 #} -title "Restic backup" -restic backup \ + +log "Restic backup" +run restic backup \ {% if backups_role_script_prepare_template == "cron-prepare.sh.j2" %} {% for db in backups_role_db_names %} "{{ backups_role_tmp_path }}/pg_dump_{{ db }}" \ @@ -8,10 +9,8 @@ restic backup \ {% endif %} {{ backups_role_assets_paths|join(' ') }} -echo "…done" - -title "Restic forget" -restic forget \ +log "Restic forget" +run restic forget \ --keep-last {{ backups_role_keep_last }} \ --keep-hourly {{ backups_role_keep_hourly }} \ --keep-daily {{ backups_role_keep_daily }} \ @@ -19,8 +18,6 @@ restic forget \ --keep-monthly {{ backups_role_keep_monthly }} \ --keep-yearly {{ backups_role_keep_yearly }} \ --prune -echo "…done" -title "Restic check" -restic check -echo "…done" +log "Restic check" +run restic check