From addeb84b2a68563d8b32289c029dde350fd91950 Mon Sep 17 00:00:00 2001
From: James Tufarelli <8152401+Minituff@users.noreply.github.com>
Date: Wed, 18 Oct 2023 15:05:34 -0700
Subject: [PATCH] Add logging (#45)
---
Dockerfile | 21 +++++++-----
docs/arguments.md | 23 +++++++++----
docs/labels.md | 3 +-
pkg/backup.sh | 85 +++++++++++++++++------------------------------
pkg/entry.sh | 44 +++++++++++++-----------
pkg/logger.sh | 33 ++++++++++++++++++
6 files changed, 118 insertions(+), 91 deletions(-)
create mode 100644 pkg/logger.sh
diff --git a/Dockerfile b/Dockerfile
index eadb71e5..a547e96d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,14 +7,14 @@ RUN apk add bash rsync tzdata dos2unix jq
# Copy all necessary files into the container (from /pkg in the repository to /app in the container)
COPY pkg app
-# Move the entrypoint script to the root directory for ease of access
-RUN mv app/entry.sh /entry.sh
+# Make the entire /app folder executable
+RUN chmod +x /app
-# Make the script executable
-RUN chmod +x app/backup.sh && dos2unix app/backup.sh
+# Make the all files in the /app folder Unix format
+RUN find /app -type f -print0 | xargs -0 dos2unix
-# Make the entry script executable
-RUN chmod +x entry.sh && dos2unix entry.sh
+# Move the entrypoint script to the root directory for ease of access
+RUN mv app/entry.sh /entry.sh
# Nautical Version (for example "v0.2.1") or "main" if not set
ARG NAUTICAL_VERSION="main"
@@ -32,9 +32,6 @@ ENV REPORT_FILE="true"
# Run the backup immediately on start
ENV BACKUP_ON_START="false"
-# Log each rsync command to console before running (useful for debugging)
-ENV LOG_RSYNC_COMMANDS="false"
-
# Use the default rsync args "-raq" (recursive, archive, quiet)
ENV USE_DEFAULT_RSYNC_ARGS="true"
@@ -44,5 +41,11 @@ ENV RSYNC_CUSTOM_ARGS=""
# Require the Docker Label `nautical-backup.enable=true` to be present on each contianer or it will be skipped.
ENV REQUIRE_LABEL="false"
+# Set the default log level to INFO
+ENV LOG_LEVEL="INFO"
+
+# Set the default log level for the repot file to INFO
+ENV REPORT_FILE_LOG_LEVEL="INFO"
+
# Run the entry script and pass all variables to it
ENTRYPOINT [ "bash", "-c", "exec ./entry.sh \"${@}\"", "--"]
diff --git a/docs/arguments.md b/docs/arguments.md
index 671770e8..dad78823 100644
--- a/docs/arguments.md
+++ b/docs/arguments.md
@@ -165,18 +165,27 @@ Will immediatly perform a backup when the container is started in addition to th
BACKUP_ON_START=true
```
-## Log rsync Commands
+## Console Log Level
+Set the console log level for the container.
-Log each `rsync` command to console before running (useful for debugging)
+> **Default**: INFO
-> **Default**: false
+> **Options**: DEBUG, INFO, WARN, ERROR
```properties
-LOG_RSYNC_COMMANDS=true
+LOG_LEVEL=INFO
```
-You should see something like this in the Nautical contianer logs:
-```console
-rsync -ahq --exclude='*.log' --exclude='*.txt' /app/source/watchtower/ /app/destination/watchtower/
+
+## Report Log Level
+Set the log level for the generated report file.
+Only used if the repot file is [enabled](#report-file).
+
+> **Default**: INFO
+
+> **Options**: DEBUG, INFO, WARN, ERROR
+
+```properties
+REPORT_FILE_LOG_LEVEL=INFO
```
## Use Default rsync Arguments
diff --git a/docs/labels.md b/docs/labels.md
index 6747516d..0b6718c4 100644
--- a/docs/labels.md
+++ b/docs/labels.md
@@ -13,6 +13,7 @@ Remember, these labels can be added to any container (other than Nautica
labels:
- "nautical-backup.enable=true"
- "nautical-backup.stop-before-backup=true"
+ - "nautical-backup.rsync-custom-args= " # Disable custom rsync args
```
=== "Docker Compose Example 2"
@@ -204,7 +205,7 @@ nautical-backup.rsync-custom-args=--exclude='*.log' --exclude='*.txt'
!!! note "This label will *override* the global setting applied through [Enviornment Variables](./arguments.md)"
* *Any value* will override the global rsync arguemnts configured through [global settings](./arguments.md#custom-rsync-arguments).
- * A (empty) value of `"nautical-backup.rsync-custom-args="` will ^^cancel^^ any [global setting](./arguments.md#custom-rsync-arguments) for this container only.
+ * A value of (space) `"nautical-backup.rsync-custom-args= "` will ^^cancel^^ any [global setting](./arguments.md#custom-rsync-arguments) for this container only.
* Not setting the label value will use the [global setting](./arguments.md#custom-rsync-arguments).
🔄 Not setting a label is the same action as the [Custom rsync Arguments](./arguments.md#custom-rsync-arguments) variable, but applied only to this container.
\ No newline at end of file
diff --git a/pkg/backup.sh b/pkg/backup.sh
index b3b49703..9b2b2066 100644
--- a/pkg/backup.sh
+++ b/pkg/backup.sh
@@ -1,6 +1,7 @@
#!/bin/bash
-echo "Starting backup script..."
+source /app/logger.sh # Use the logger script
+logThis "Starting backup..."
# Convert the string back to an array
if [ ! -z "$CONTAINER_SKIP_LIST_STR" ]; then
@@ -39,55 +40,31 @@ containers=$(docker ps --no-trunc --format="{{.ID}}:{{.Names}}")
number_of_containers=$(echo "$containers" | wc -l)
number_of_containers=$((number_of_containers - 1)) # Subtract 1 to exclude the container running the script
-echo "Processing $number_of_containers containers..."
+logThis "Processing $number_of_containers containers..."
# Define the name for the report file
report_file="Backup Report - $(date +'%Y-%m-%d').txt"
-# Remove previous report files
-
-# Initialize the current report file with a header
-if [ "$REPORT_FILE" = "true" ]; then
- rm -f "$DEST_LOCATION/Backup Report - "*.txt
- # Initialize the current report file with a header
- echo "Backup Report - $(date)" >"$DEST_LOCATION/$report_file"
-fi
DEFAULT_RSYNC_ARGS="-ahq"
default_rsync_args="-ahq"
if [ "$USE_DEFAULT_RSYNC_ARGS" = "false" ]; then
+ logThis "Disabling default rsync arguments ($DEFAULT_RSYNC_ARGS)" "DEBUG"
default_rsync_args=""
fi
# Global variables to hold rsync arguments
custom_args=""
if [ ! -z "$RSYNC_CUSTOM_ARGS" ]; then
+ logThis "Adding custom rsync arguments ($RSYNC_CUSTOM_ARGS)" "DEBUG"
custom_args="$RSYNC_CUSTOM_ARGS"
fi
-# Get arguments:
-# -s = skips
-# -d = override DEST_LOCATION
-while getopts ":s:d:" opt; do
- case $opt in
- s) currs+=("$OPTARG") ;;
- d) DEST_LOCATION=$OPTARG ;;
- esac
-done
# Merge the default skips with provided skips
currs=("${currs[@]}" "${SKIP_CONTAINERS[@]}")
containers_completed=0
-# Assumes the container name is the exact same as the directory name
-log_entry() {
- local message="$1"
- echo "$message"
-
- if [ "$REPORT_FILE" = "true" ]; then
- echo "$(date) - $message" >>"$DEST_LOCATION/$report_file"
- fi
-}
BackupContainer() {
local container=$1
@@ -96,7 +73,7 @@ BackupContainer() {
for skip in "${SKIP_STOPPING[@]}"; do
if [ "$skip" == "$container" ]; then
skip_stopping=1
- log_entry "Skipping stopping of $container as it's in the SKIP_STOPPING list."
+ logThis "Skipping stopping of $container as it's in the SKIP_STOPPING list." "DEBUG"
break
fi
done
@@ -105,81 +82,81 @@ BackupContainer() {
labels=$(docker inspect --format '{{json .Config.Labels}}' $id)
if echo "$labels" | grep -q '"nautical-backup.stop-before-backup":"false"'; then
- log_entry "Skipping stopping of $container because of label."
+ logThis "Skipping stopping of $container because of label." "DEBUG"
skip_stopping=1
fi
local src_dir="$SOURCE_LOCATION/$container"
if [ ! -z "${override_source_dirs[$container]}" ]; then
src_dir="$SOURCE_LOCATION/${override_source_dirs[$container]}"
- log_entry "Overriding source directory for $container to ${override_source_dirs[$container]}"
+ logThis "Overriding source directory for $container to ${override_source_dirs[$container]}" "DEBUG"
fi
if echo "$labels" | grep -q '"nautical-backup.override-source-dir"'; then
new_src_dir=$(echo "$labels" | jq -r '.["nautical-backup.override-source-dir"]')
src_dir="$SOURCE_LOCATION/$new_src_dir"
- log_entry "Overriding source directory for $container to $new_src_dir from label"
+ logThis "Overriding source directory for $container to $new_src_dir from label" "DEBUG"
fi
local dest_dir="$DEST_LOCATION/$container"
if [ ! -z "${override_dest_dirs[$container]}" ]; then
dest_dir="$DEST_LOCATION/${override_dest_dirs[$container]}"
- log_entry "Overriding destination directory for $container to ${override_dest_dirs[$container]}"
+ logThis "Overriding destination directory for $container to ${override_dest_dirs[$container]}" "DEBUG"
fi
if echo "$labels" | grep -q '"nautical-backup.override-destination-dir"'; then
new_destination_dir=$(echo "$labels" | jq -r '.["nautical-backup.override-destination-dir"]')
dest_dir="$DEST_LOCATION/$new_destination_dir"
- log_entry "Overriding destination directory for $container to $new_destination_dir from label"
+ logThis "Overriding destination directory for $container to $new_destination_dir from label" "DEBUG"
fi
if [ -d "$src_dir" ]; then
if [ $skip_stopping -eq 0 ]; then
- log_entry "Stopping $container..."
+ logThis "Stopping $container..."
docker stop $container 2>&1 >/dev/null
if [ $? -ne 0 ]; then
- log_entry "Error stopping container $container. Skipping backup for this container."
+ logThis "Error stopping container $container. Skipping backup for this container." "ERROR"
return
fi
fi
if echo "$labels" | grep -q '"nautical-backup.use-default-rsync-args":"true"'; then
- echo "Using default rsync args ($DEFAULT_RSYNC_ARGS) for $container"
+ logThis "Using default rsync args ($DEFAULT_RSYNC_ARGS) for $container" "DEBUG"
default_rsync_args=$DEFAULT_RSYNC_ARGS
elif echo "$labels" | grep -q '"nautical-backup.use-default-rsync-args":"false"'; then
- echo "Not using default rsync args ($DEFAULT_RSYNC_ARGS) for $container"
+ logThis "Not using default rsync args ($DEFAULT_RSYNC_ARGS) for $container" "DEBUG"
default_rsync_args=""
fi
if echo "$labels" | grep -q '"nautical-backup.rsync-custom-args"'; then
new_custom_rsync_args=$(echo "$labels" | jq -r '.["nautical-backup.rsync-custom-args"]')
custom_args=$new_custom_rsync_args
- echo "Using custom rsync args for $container"
+ logThis "Using custom rsync args for $container" "DEBUG"
fi
- log_entry "Backing up $container data..."
- if [ "$LOG_RSYNC_COMMANDS" = "true" ]; then
- echo rsync $default_rsync_args $custom_args $src_dir/ $dest_dir/
- fi
+ logThis "Backing up $container data..."
+ logThis "RUNNING: 'rsync $default_rsync_args $custom_args $src_dir/ $dest_dir/'" "DEBUG"
+
+ # Run rsync
eval rsync $default_rsync_args $custom_args $src_dir/ $dest_dir/
if [ $? -ne 0 ]; then
- log_entry "Error copying data for container $container. Skipping backup for this container."
+ logThis "Error copying data for container $container. Skipping backup for this container." "ERROR"
fi
if [ $skip_stopping -eq 0 ]; then
- log_entry "Starting $container container..."
+ logThis "Starting $container container..."
docker start $container 2>&1 >/dev/null
if [ $? -ne 0 ]; then
- log_entry "Error restarting container $container. Please check manually!"
+ logThis "Error restarting container $container. Please check manually!" "ERROR"
return
fi
fi
- log_entry "$container completed."
+ logThis "$container completed."
((containers_completed++))
else
- log_entry "Directory $src_dir does not exist. Skipping"
+ logThis "Directory $src_dir does not exist. Skipping" "WARN"
fi
}
@@ -198,21 +175,21 @@ for entry in $containers; do
labels=$(docker inspect --format '{{json .Config.Labels}}' $id)
if echo "$labels" | grep -q '"nautical-backup.enable":"true"'; then
- echo "Enabling $name based on label."
+ logThis "Enabling $name based on label." "DEBUG"
skip=0 # Do not skip the container
elif echo "$labels" | grep -q '"nautical-backup.enable":"false"'; then
- echo "Skipping $name based on label."
+ logThis "Skipping $name based on label." "DEBUG"
skip=1 # Add the container to the skip list
elif [ "$REQUIRE_LABEL" = "true" ]; then
if [ "$id" != "$SELF_CONTAINER_ID" ]; then
- echo "Skipping $name as 'nautical-backup.enable=true' was not found and REQUIRE_LABEL is true."
+ echo "Skipping $name as 'nautical-backup.enable=true' was not found and REQUIRE_LABEL is true." "DEBUG"
fi
fi
for cur in "${SKIP_CONTAINERS[@]}"; do
if [ "$cur" == "$name" ]; then
skip=1
- echo "Skipping $name based on name."
+ echo "Skipping $name based on name." "DEBUG"
break
fi
if [ "$cur" == "$id" ]; then
@@ -220,7 +197,7 @@ for entry in $containers; do
if [ "$cur" == "$SELF_CONTAINER_ID" ]; then
break # Exclude self from logs
fi
- echo "Skipping $name based on ID $id."
+ echo "Skipping $name based on ID $id." "DEBUG"
break
fi
done
@@ -232,4 +209,4 @@ done
containers_skipped=$((number_of_containers - containers_completed))
-echo "Success. $containers_completed containers backed up! $containers_skipped skipped."
+logThis "Success. $containers_completed containers backed up! $containers_skipped skipped." "INFO"
diff --git a/pkg/entry.sh b/pkg/entry.sh
index 456d973b..642c47cf 100644
--- a/pkg/entry.sh
+++ b/pkg/entry.sh
@@ -1,9 +1,13 @@
#!/bin/bash
+source /app/logger.sh # Use the logger script
-echo "Nautical Backup Version: $NAUTICAL_VERSION"
+create_new_report_file
+
+logThis "Nautical Backup Version: $NAUTICAL_VERSION"
+logThis "Using log level: $LOG_LEVEL" "DEBUG"
# Echo the CRON schedule for logging/debugging
-echo "Installing CRON schedule: $CRON_SCHEDULE in TZ: $TZ"
+logThis "Installing CRON schedule: $CRON_SCHEDULE in TZ: $TZ" "DEBUG"
# Dump the current cron jobs to a temporary file
crontab -l > tempcron
@@ -23,24 +27,24 @@ export SOURCE_LOCATION=/app/source # Do not include a trailing slash
export DEST_LOCATION=/app/destination # Do not include a trailing slash
-echo "Verifying source directory..."
+logThis "Verifying source directory..." "DEBUG"
if [ ! -d "$SOURCE_LOCATION" ]; then
- echo "Error: Source directory $SOURCE_LOCATION does not exist."
+ logThis "Error: Source directory $SOURCE_LOCATION does not exist."
exit 1
elif [ ! -r "$SOURCE_LOCATION" ]; then
- echo "Error: No read access to source directory $SOURCE_LOCATION."
+ logThis "Error: No read access to source directory $SOURCE_LOCATION."
exit 1
fi
-echo "Verifying destination directory..."
+logThis "Verifying destination directory..." "DEBUG"
if [ ! -d "$DEST_LOCATION" ]; then
- echo "Error: Destination directory $DEST_LOCATION does not exist."
+ logThis "Error: Destination directory $DEST_LOCATION does not exist." "ERROR"
exit 1
elif [ ! -r "$DEST_LOCATION" ]; then
- echo "Error: No read access to destination directory $DEST_LOCATION."
+ logThis "Error: No read access to destination directory $DEST_LOCATION." "ERROR"
exit 1
elif [ ! -w "$DEST_LOCATION" ]; then
- echo "Error: No write access to destination directory $DEST_LOCATION."
+ logThis "Error: No write access to destination directory $DEST_LOCATION." "ERROR"
exit 1
fi
@@ -73,11 +77,11 @@ process_csv SKIP_STOPPING_LIST "$SKIP_STOPPING"
if [ ! -z "$SKIP_CONTAINERS" ]; then
- echo "SKIP_CONTAINERS: ${CONTAINER_SKIP_LIST[@]}"
+ logThis "SKIP_CONTAINERS: ${CONTAINER_SKIP_LIST[@]}" "DEBUG"
fi
if [ ! -z "$SKIP_STOPPING" ]; then
- echo "SKIP_STOPPING: ${SKIP_STOPPING_LIST[@]}"
+ logThis "SKIP_STOPPING: ${SKIP_STOPPING_LIST[@]}" "DEBUG"
fi
# Get the container ID of the current container
@@ -93,43 +97,43 @@ export SKIP_STOPPING_STR # Export the string
# Assuming OVERRIDE_SOURCE_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..."
if [ ! -z "$OVERRIDE_SOURCE_DIR" ]; then
- echo "OVERRIDE_SOURCE_DIR: ${OVERRIDE_SOURCE_DIR}"
+ logThis "OVERRIDE_SOURCE_DIR: ${OVERRIDE_SOURCE_DIR}" "DEBUG"
fi
export OVERRIDE_SOURCE_DIR
# Assuming OVERRIDE_DEST_DIR is passed as an environment variable in the format "container1:dir1,container2:dir2,..."
if [ ! -z "$OVERRIDE_DEST_DIR" ]; then
- echo "OVERRIDE_DEST_DIR: ${OVERRIDE_DEST_DIR}"
+ logThis "OVERRIDE_DEST_DIR: ${OVERRIDE_DEST_DIR}" "DEBUG"
fi
export OVERRIDE_DEST_DIR
if [ "$REPORT_FILE" = "false" ]; then
- echo "REPORT_FILE: $REPORT_FILE"
+ logThis "REPORT_FILE: $REPORT_FILE" "DEBUG"
fi
# Set rsync custom arguments if specified
if [ ! -z "$RSYNC_CUSTOM_ARGS" ]; then
- echo "RSYNC_CUSTOM_ARGS: $RSYNC_CUSTOM_ARGS"
+ logThis "RSYNC_CUSTOM_ARGS: $RSYNC_CUSTOM_ARGS" "DEBUG"
fi
if [ "$LOG_RSYNC_COMMANDS" = "true" ]; then
- echo "LOG_RSYNC_COMMANDS: $LOG_RSYNC_COMMANDS"
+ logThis "LOG_RSYNC_COMMANDS: $LOG_RSYNC_COMMANDS" "DEBUG"
fi
if [ "$USE_DEFAULT_RSYNC_ARGS" = "false" ]; then
- echo "USE_DEFAULT_RSYNC_ARGS: $USE_DEFAULT_RSYNC_ARGS"
+ logThis "USE_DEFAULT_RSYNC_ARGS: $USE_DEFAULT_RSYNC_ARGS" "DEBUG"
fi
if [ "$REQUIRE_LABEL" = "true" ]; then
- echo "REQUIRE_LABEL: $REQUIRE_LABEL"
+ logThis "REQUIRE_LABEL: $REQUIRE_LABEL" "DEBUG"
fi
if [ "$BACKUP_ON_START" = "true" ]; then
- echo "BACKUP_ON_START: $BACKUP_ON_START"
+ logThis "BACKUP_ON_START: $BACKUP_ON_START" "DEBUG"
bash ./app/backup.sh
fi
-echo "Initialization complete. Awaiting CRON schedule: $CRON_SCHEDULE"
+logThis "Initialization complete. Awaiting CRON schedule: $CRON_SCHEDULE"
diff --git a/pkg/logger.sh b/pkg/logger.sh
new file mode 100644
index 00000000..e3bce629
--- /dev/null
+++ b/pkg/logger.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+declare -A levels=([DEBUG]=0 [INFO]=1 [WARN]=2 [ERROR]=3)
+script_logging_level=$LOG_LEVEL
+report_file_logging_level=$REPORT_FILE_LOG_LEVEL
+
+report_file="Backup Report - $(date +'%Y-%m-%d').txt"
+
+create_new_report_file() {
+ if [ "$REPORT_FILE" = "true" ]; then
+ rm -f "$DEST_LOCATION/Backup Report - "*.txt
+ # Initialize the current report file with a header
+ echo "Backup Report - $(date)" >"$DEST_LOCATION/$report_file"
+ fi
+}
+
+logThis() {
+ local log_message=$1
+ local log_priority=${2:-INFO}
+
+ # Check if level exists
+ [[ ${levels[$log_priority]} ]] || return 1
+
+ # Check if level is enough for console logging
+ if ((${levels[$log_priority]} >= ${levels[$script_logging_level]})); then
+ echo "${log_priority}: ${log_message}"
+ fi
+
+ # Check if level is enough for report file logging
+ if [ "$REPORT_FILE" = "true" ] && ((${levels[$log_priority]} >= ${levels[$report_file_logging_level]})); then
+ echo "$(date) - ${log_priority}: ${log_message}" >>"$DEST_LOCATION/$report_file"
+ fi
+}