CouchDB - 'DB Backup exit Code is <blank>'
Summary
The backup process for a CouchDB instance stops due to an "error" after the compression-step and during the check_exit_code-step.
Steps to reproduce
Setup a Docker instance of db-backup to backup a CouchDB instance. Use simple environment variables as listed under Environment.
Relevant logs and/or screenshots
Note that the exit_code variable is empty (non-existent).
Partial log
2025-01-29.21:23:06 [DEBUG] /etc/services.available/dbbackup-03/run ** [03-couchdb__ALL] Backup 03 routines started time: 2025-01-29 21:23:06 CET
+ bootstrap_filesystem
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ '[' '!' -d /backup/couch ']'
++ stat -c %U /backup/couch
+ '[' dbbackup '!=' dbbackup ']'
++ stat -c %a /backup/couch
+ '[' 700 '!=' 700 ']'
+ '[' -d /backup/archive/ ']'
+ '[' '!' -d /logs ']'
++ stat -c %U /logs
+ '[' dbbackup '!=' dbbackup ']'
++ date +%Y%m%d
+ '[' '!' -d /logs/20250129 ']'
++ stat -c %a /logs
+ '[' 755 '!=' 755 ']'
+ '[' '!' -d /tmp/backups ']'
++ stat -c %U /tmp/backups
+ '[' dbbackup '!=' dbbackup ']'
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ check_availability
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ var_false FALSE
+ '[' false = false ']'
+ case "${dbtype}" in
+ counter=0
+ code_received=0
+ '[' -n admin ']'
+ '[' -n OMITTED ']'
+ _ca_couch_auth='-u admin:OMITTED'
+ '[' 0 '!=' 200 ']'
++ run_as_user curl -XGET -sSL -o /dev/null -L -w '%{http_code}' -u admin:OMITTED couchdb:5984
++ sudo -Eu dbbackup curl -XGET -sSL -o /dev/null -L -w '%{http_code}' -u admin:OMITTED couchdb:5984
+ code_received=200
+ '[' 200 = 200 ']'
+ break
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ backup_couch
+ prepare_dbbackup
+ timer backup start
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ case "${1}" in
+ case "${2}" in
++ run_as_user date +%s
++ sudo -Eu dbbackup date +%s
+ dbbackup_start_time=1738182186
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
++ run_as_user date +%Y%m%d-%H%M%S
++ sudo -Eu dbbackup date +%Y%m%d-%H%M%S
+ now=20250129-212306
++ mktemp -d -p /tmp/backups -t 03_dbbackup.XXXXXX
+ temporary_directory=/tmp/backups/03_dbbackup.xevc0G
+ chown -R dbbackup:dbbackup /tmp/backups/03_dbbackup.xevc0G
+ backup_job_filename_base=couch_all_couchdb
+ backup_job_filename=couch_all_couchdb_20250129-212306.sql
+ backup_job_filename=couch_ALL_couchdb_20250129-212306.txt
+ backup_job_filename_base=couch_ALL_couchdb
+ compression
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ var_false TRUE
+ '[' true = false ']'
+ '[' true = no ']'
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ case "${backup_job_compression,,}" in
+ print_debug '[compression] Selected ZSTD'
+ output_off
+ '[' true = true ']'
+ set +x
2025-01-29.21:23:06 [DEBUG] /etc/services.available/dbbackup-03/run ** [03-couchdb__ALL] [compression] Selected ZSTD
+ compress_cmd=' zstd -q -q --rm -3 -T12 '
+ compression_type=zstd
+ dir_compress_cmd=' zstd -q -q --rm -3 -T12 '
+ extension=.zst
+ backup_job_filename_dir=couch_ALL_couchdb_20250129-212306.txt
+ backup_job_filename=couch_ALL_couchdb_20250129-212306.txt.zst
+ case "${CONTAINER_LOG_LEVEL,,}" in
+ '[' zstd = none ']'
+ compression_string='and compressing with '\''zstd:3'\'' with '\''12'\'' threads'
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ check_exit_code backup couch_ALL_couchdb_20250129-212306.txt.zst
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ case "${1}" in
+ write_log debug 'DB Backup exit Code is '
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ output_off
+ '[' true = true ']'
+ set +x
2025-01-29.21:23:06 [DEBUG] /etc/services.available/dbbackup-03/run ** [03-couchdb__ALL] DB Backup exit Code is
+ output_on
+ '[' true = true ']'
+ case "$(basename "$0")" in
++ basename ./run
+ case "$PWD" in
+ set -x
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ case "${exit_code}" in
+ write_log error 'DB Backup of '\''couch_ALL_couchdb_20250129-212306.txt.zst'\'' reported errors'
+ var_true ''
+ '[' '' = true ']'
+ '[' '' = yes ']'
+ output_off
+ '[' true = true ']'
+ set +x
2025-01-29.21:23:06 [ERROR] /etc/services.available/dbbackup-03/run ** [03-couchdb__ALL] DB Backup of 'couch_ALL_couchdb_20250129-212306.txt.zst' reported errors
...
Environment
- Image version / tag: 4.1.15
- Host OS: Unraid | Docker
Environment variables
DB03_TYPE=couch DB03_HOST=couchdb DB03_PORT=5984 DB03_NAME=ALL DB03_USER=admin DB03_PASS=OMITTED DB03_FILESYSTEM_PATH=/backup/couch DB03_SPLIT_DB=FALSE
Possible fixes
The variable exit_code is never set and thus results in an error during check_exit_code. Either removing this check or setting the variable based on the output of a command should resolve this.
Besides the issue of exit_code being empty as far as I can tell there is no code actually responsible for backing up the CouchDB instance. I would expect this to happen somewhere in 10-db-backup:532-537. However I could be wrong about this.
You aren't wrong, I cobbled this quickly together - it will backup all couchdb databases, exclusion should work as well. Just replace the backup_couch section with this.
Note that if you make a change to docker-compose.yml, eg enable/disable DEBUG=TRUE, you will need to update /assets/functions/10-db-backup again
backup_couch() {
if [ "${backup_job_db_name,,}" = "all" ] ; then
write_log debug "Preparing to back up all databases"
db_names=$(run_as_user curl -X GET -s -u "${backup_job_db_user}:${backup_job_db_pass}" "${backup_job_db_host}:${backup_job_db_port}/_all_dbs" | tr -d '[]"' | tr ',' '\n' )
if [ -n "${backup_job_db_name_exclude}" ] ; then
db_names_exclusions=$(echo "${backup_job_db_name_exclude}" | tr ',' '\n')
for db_exclude in ${db_names_exclusions} ; do
write_log debug "Excluding '${db_exclude}' from ALL DB_NAME backups"
db_names=$(echo "$db_names" | sed "/${db_exclude}/d" )
done
fi
else
db_names=$(echo "${backup_job_db_name}" | tr ',' '\n')
fi
if var_true "${DEBUG_BACKUP_COUCH}" ; then debug off; fi
write_log debug "Databases Found: $(echo ${db_names} | xargs | tr ' ' ',')"
for db in ${db_names} ; do
prepare_dbbackup
backup_job_filename=couch_${db}_${backup_job_db_host,,}_${now}.txt
backup_job_filename_base=couch_${db}_${backup_job_db_host,,}
compression
pre_dbbackup "${db}"
write_log notice "Dumping CouchDB database: '${db}' ${compression_string}"
if var_true "${DEBUG_BACKUP_COUCH}" ; then debug on; fi
run_as_user ${play_fair} curl -s -X GET -u "${backup_job_db_user}:${backup_job_db_pass}" "${backup_job_db_host}:${backup_job_db_port}/$db/_all_docs?include_docs=true&attachments=true" | ${compress_cmd} | run_as_user tee "${temporary_directory}"/"${backup_job_filename}" > /dev/null
exit_code=$?
if var_true "${DEBUG_BACKUP_COUCH}" ; then debug off; fi
check_exit_code backup "${backup_job_filename}"
timer backup finish
file_encryption
generate_checksum
move_dbbackup
check_exit_code move "${backup_job_filename}"
post_dbbackup "${db}"
cleanup_old_data
done
}