Pass backup name as variable to before/after script

I want to create a before/after script to stop docker containers, was wondering if there is a duplicati environment variable that passes the backup job name that can be used in the script?

Example:
Backup Name: Plex
Environment variable: DUPLICATI__[JOBNAME] = “Plex”

This way I can use the backup name in a variable in the script to do something specific based on the backup name passed to the script.

There is DUPLICATI__backup_name which is set to the name of the backup.

Some other variables (but it seems not this one) are documented in the manual article.

You could also try to use remoteurl or local path for this.

Thank you @Jojo-1000 that is working perfectly. :slight_smile:

<<<=== Backup
Script start: Sun Jun 25 09:07:36 PM CAT 2023
Duplicati job name: cloudcmd
Finding docker container: cloudcmd
Duplicati running BEFORE event script
Found container: cloudcmd
Stopping container: cloudcmd
Container cloudcmd running state: false
Container cloudcmd stopped…
Script stopped: Sun Jun 25 09:07:49 PM CAT 2023
===>>>
<<<=== Backup
Script start: Sun Jun 25 09:08:15 PM CAT 2023
Duplicati job name: cloudcmd
Finding docker container: cloudcmd
Duplicati running AFTER event script
Found container: cloudcmd
Starting container: cloudcmd
Container cloudcmd running state: true
Container cloudcmd started…
Script stopped: Sun Jun 25 09:08:17 PM CAT 2023
===>>>

The script if anyone is interested.

Script is meant to backup individual containers based on the container name. Make sure to name the backup job the same as your docker container.

#!/bin/bash
logfile=/config/docker_backup.log # /cofig is the location within duplicati docker _data directory

# Get duplicati job name which should be same as docker container name for script to work
dupdocker=${DUPLICATI__backup_name}
#dupdocker=ombi

# Get duplicati script event: BEFORE/AFTER
dupevent=${DUPLICATI__EVENTNAME}
#dupevent=BEFORE

# Get duplicati operation event: "Backup", "Cleanup", "Restore", or "DeleteAllButN"
dupopevent=${DUPLICATI__OPERATIONNAME}

if [ $dupopevent == "Backup" ]; then
    printf "<<<=== ${dupopevent}\n" | tee -a $logfile
    printf "Script start: $(date)\n" | tee -a $logfile
    printf "Duplicati job name: ${dupdocker}\n" | tee -a $logfile

    printf "Finding docker container: ${dupdocker}\n" | tee -a $logfile
    runcont=$(docker ps -a -f name=${dupdocker} --format '{{.Names}}')

    # Check if duplicati event if BEFORE script
    if [ $dupevent == "BEFORE" ]; then
    printf "Duplicati running BEFORE event script\n" | tee -a $logfile

    # Check if docker container was found
    if [ $dupdocker == $runcont ]; then
        printf "Found container: ${runcont}\n" | tee -a $logfile
        printf "Stopping container: ${runcont}\n" | tee -a $logfile

        # Stop running docker container
        $(docker stop $runcont > /dev/null 2>&1)

        # Check state of docker container
        docstate=$(docker inspect -f {{.State.Running}} $runcont)
        printf "Container ${runcont} running state: ${docstate}\n" | tee -a $logfile

        if [ $docstate == "false" ]; then
        printf "Container ${runcont} stopped...\n" | tee -a $logfile
        else
        printf "Container ${runcont} still running, should be stopped!!!\n" | tee -a $logfile
        fi

    else
        printf "No container found named: ${dupdocker}\n" | tee -a $logfile
    fi
    else
    printf "Duplicati running AFTER event script\n" | tee -a $logfile

    # Check if docker container was found
    if [ $dupdocker == $runcont ]; then
        printf "Found container: ${runcont}\n" | tee -a $logfile
        printf "Starting container: ${runcont}\n" | tee -a $logfile

        # Start stopped docker container
        $(docker start $runcont > /dev/null 2>&1)

        # Check state of docker container
        docstate=$(docker inspect -f {{.State.Running}} $runcont)
        printf "Container ${runcont} running state: ${docstate}\n" | tee -a $logfile

        if [ "$docstate" == "true" ]; then
        printf "Container ${runcont} started...\n" | tee -a $logfile
        else
        printf "Container ${runcont} still not running, should be started!!!\n" | tee -a $logfile
        fi
    else
        printf "No container found named: ${dupdocker}\n" | tee -a $logfile
    fi
    fi
    printf "Script stopped: $(date)\n" | tee -a $logfile
    printf "===>>>\n" | tee -a $logfile
fi

Note: This is my first bash script, so use at own risk :slight_smile:

1 Like

check https://github.com/Sn00zEZA/docker/tree/main/duplicati for updates to the script

1 Like

The script works perfectly! THX

I modified the script to find all containers and gradually stop/start them.

Duplicati - Advanced Options:
run-script-before
run-script-after

#!/bin/bash
# Output to console, logfile, and docker log stdout. # fd/1 for stdout
# | tee /proc/1/fd/1 -a $logfile
logfile=/home/mirino/config/docker_backup.log # /config is the location within duplicati docker _data directory

# Get duplicati script event: BEFORE/AFTER
dupevent=${DUPLICATI__EVENTNAME}

# Get duplicati operation event: "Backup", "Cleanup", "Restore", or "DeleteAllButN"
dupopevent=${DUPLICATI__OPERATIONNAME}

if [ $dupopevent == "Backup" ]; then
    event_name=" ${dupopevent} \"${DUPLICATI__backup_name}\""
    separator_length=$(( ${#event_name} + 1 ))
    separator=$(printf '=%.0s' $(seq 1 $separator_length))
    printf "\n" | tee /proc/1/fd/1 -a $logfile
    printf "$separator\n" | tee /proc/1/fd/1 -a $logfile
    printf "$event_name\n" | tee /proc/1/fd/1 -a $logfile
    printf "$separator\n" | tee /proc/1/fd/1 -a $logfile
    printf "Script start: $(date)\n" | tee /proc/1/fd/1 -a $logfile

    printf "Duplicati event: ${dupevent}\n" | tee /proc/1/fd/1 -a $logfile

    if [ $dupevent == "BEFORE" ]; then
        printf "Duplicati running BEFORE event script\n" | tee /proc/1/fd/1 -a $logfile

        printf "Found $(docker ps -aq | wc -l) Docker containers\n" | tee /proc/1/fd/1 -a $logfile
        containers=$(docker ps -aq)
        total_containers=$(echo "$containers" | wc -w)
        container_counter=0
        printf ".....................................................\n" | tee /proc/1/fd/1 -a $logfile
        if [ -n "$containers" ]; then
            for container in $containers; do
                container_counter=$((container_counter+1))
                container_name=$(docker inspect --format '{{.Name}}' $container | sed 's/^\///')
                printf "\n Stopping container ($container_counter/$total_containers): $container_name ($container)\n" | tee /proc/1/fd/1 -a $logfile
                docker stop $container > /dev/null 2>&1

                docstate=$(docker inspect -f {{.State.Running}} $container)
                printf "   Container running state: $docstate\n" | tee /proc/1/fd/1 -a $logfile

                if [ "$docstate" == "false" ]; then
                    printf "   Container stopped\n" | tee /proc/1/fd/1 -a $logfile
                else
                    printf "Container $container_name ($container) still not running, should be started!!!\n" | tee /proc/1/fd/1 -a $logfile
                fi
                printf ".....................................................\n" | tee /proc/1/fd/1 -a $logfile
            done
        else
            printf "No Docker containers found\n" | tee /proc/1/fd/1 -a $logfile
        fi
    else
        printf "Duplicati running AFTER event script\n" | tee /proc/1/fd/1 -a $logfile

        printf "Found $(docker ps -aq | wc -l) Docker containers\n" | tee /proc/1/fd/1 -a $logfile
        printf ".....................................................\n" | tee /proc/1/fd/1 -a $logfile
        containers=$(docker ps -aq)
        total_containers=$(echo "$containers" | wc -w)
        container_counter=0

        if [ -n "$containers" ]; then
            for container in $containers; do
                container_counter=$((container_counter+1))
                container_name=$(docker inspect --format '{{.Name}}' $container | sed 's/^\///')
                printf " Starting container ($container_counter/$total_containers): $container_name ($container)\n" | tee /proc/1/fd/1 -a $logfile
                docker start $container > /dev/null 2>&1

                docstate=$(docker inspect -f {{.State.Running}} $container)
                printf "   Container running state: $docstate\n" | tee /proc/1/fd/1 -a $logfile

                if [ "$docstate" == "true" ]; then
                    printf "   Container started\n" | tee /proc/1/fd/1 -a $logfile
                else
                    printf "Container $container_name ($container) still not running, should be started!!!\n" | tee /proc/1/fd/1 -a $logfile
                fi
                printf ".....................................................\n" | tee /proc/1/fd/1 -a $logfile
            done
        else
            printf "No Docker containers found\n" | tee /proc/1/fd/1 -a $logfile
        fi
    fi

    printf "Script stopped: $(date)\n" | tee /proc/1/fd/1 -a $logfile
    printf "$separator\n" | tee /proc/1/fd/1 -a $logfile
fi

Output from log:

=========================
 Backup "ALL CONTAINERS"
=========================
Script start: Wed  8 Nov 09:24:21 GMT 2023
Duplicati event: BEFORE
Duplicati running BEFORE event script
Found 2 Docker containers
.....................................................

 Stopping container (1/2): mariadbtest (5bceeb32bff2)
   Container running state: false
   Container stopped
.....................................................

 Stopping container (2/2): compassionate_curie (ed4875d4b374)
   Container running state: false
   Container stopped
.....................................................
Script stopped: Wed  8 Nov 09:24:26 GMT 2023
=========================

=========================
 Backup "ALL CONTAINERS"
=========================
Script start: Wed  8 Nov 09:24:27 GMT 2023
Duplicati event: AFTER
Duplicati running AFTER event script
Found 2 Docker containers
.....................................................
 Starting container (1/2): mariadbtest (5bceeb32bff2)
   Container running state: true
   Container started
.....................................................
 Starting container (2/2): compassionate_curie (ed4875d4b374)
   Container running state: true
   Container started
.....................................................
Script stopped: Wed  8 Nov 09:24:31 GMT 2023
=========================

I have took the script - thank you so much.
Here is my variant of the script but with Notification to Telegram.
But if you have many containers, make sure you add ‘run-script-timeout’ to Advanced options (the same place where the options are set - run-script-before / run-script-after), because the default value is 60s and the backup may start before all containers are stopped.

#!/bin/bash
### GLOBAL VARIABLES ####
###https://duplicati.readthedocs.io/en/latest/appendix-g-example-scripts/#run-script-examplesh
# Duplicati variables
EVENTNAME=$DUPLICATI__EVENTNAME
OPERATIONNAME=$DUPLICATI__OPERATIONNAME
REMOTEURL=$DUPLICATI__REMOTEURL
# My variables
today=$(date +"%Y-%m-%d")
Telegram_TOKEN="YUOR_Telegram_TOKEN" # replace 'YUOR_Telegram_TOKEN' with your Telegram_TOKEN
Telegram_CHAT_ID="YUOR_Telegram_CHAT_ID" # replace 'YUOR_Telegram_CHAT_ID' with your Telegram_CHAT_ID
Telegram_SUCCESS="✅"
Telegram_ERROR="💥🔴"
logfile=/home/USERNAME/duplicatiLog/docker_backup.log # !!!!!!! replace 'USERNAME' with name of your system user or select a different location 

# Get duplicati script event: BEFORE/AFTER
dupevent=${DUPLICATI__EVENTNAME}
# Get duplicati operation event: "Backup", "Cleanup", "Restore", or "DeleteAllButN"
dupopevent=${DUPLICATI__OPERATIONNAME}

# List to keep track of container states
started_containers_file="/home/USERNAME/duplicatiLog/started_containers.txt" # !!!!!!! replace 'USERNAME' with name of your system user or select a different location 

if [ "$dupevent" == "BEFORE" ]; then
    printf "Duplicati running BEFORE event script\n" | tee /proc/1/fd/1 -a "$logfile"
    printf "Found $(docker ps -aq | wc -l) Docker containers\n" | tee /proc/1/fd/1 -a "$logfile"
    containers=$(docker ps -q)
    total_containers=$(echo "$containers" | wc -w)
    container_counter=0
    printf ".....................................................\n" | tee /proc/1/fd/1 -a "$logfile"
    if [ -n "$containers" ]; then
        > "$started_containers_file" # Clear the file
        for container in $containers; do
            container_counter=$((container_counter+1))
            container_name=$(docker inspect --format '{{.Name}}' "$container" | sed 's/^\///')
            printf "\n Stopping container ($container_counter/$total_containers): $container_name ($container)\n" | tee /proc/1/fd/1 -a "$logfile"
            docker stop "$container" > /dev/null 2>&1

            docstate=$(docker inspect -f {{.State.Running}} "$container")
            printf "   Container running state: $docstate\n" | tee /proc/1/fd/1 -a "$logfile"

            if [ "$docstate" == "false" ]; then
                printf "   Container stopped\n" | tee /proc/1/fd/1 -a "$logfile"
                echo "$container" >> "$started_containers_file" # Record the stopped containers
            else
                printf "Container $container_name ($container) still not running, should be started!!!\n" | tee /proc/1/fd/1 -a "$logfile"
            fi
            printf ".....................................................\n" | tee /proc/1/fd/1 -a "$logfile"
        done
    else
        printf "No Docker containers found\n" | tee /proc/1/fd/1 -a "$logfile"
    fi

        # Check success and send to Telegram
        if [ $? -eq 0 ]; then
            # If successful, send a notification
            DATE_TIME=$(date +'%Y-%m-%d %H:%M')
            MESSAGE="$Telegram_SUCCESS $DATE_TIME"
        else
            # If unsuccessful, send a notification
            DATE_TIME=$(date +'%Y-%m-%d %H:%M')
            MESSAGE="$Telegram_ERROR $DATE_TIME"
        fi
        curl -s -X POST "https://api.telegram.org/bot$Telegram_TOKEN/sendMessage" -d "chat_id=$Telegram_CHAT_ID&text=Docker containers are stopped $MESSAGE"

elif [ "$dupevent" == "AFTER" ]; then
    printf "Duplicati running AFTER event script\n" | tee /proc/1/fd/1 -a "$logfile"
    printf "Found $(cat "$started_containers_file" | wc -l) Docker containers to start\n" | tee /proc/1/fd/1 -a "$logfile"
    printf ".....................................................\n" | tee /proc/1/fd/1 -a "$logfile"
    started_containers=$(cat "$started_containers_file")
    total_containers=$(echo "$started_containers" | wc -w)
    container_counter=0

    if [ -n "$started_containers" ]; then
        for container in $started_containers; do
            container_counter=$((container_counter+1))
            container_name=$(docker inspect --format '{{.Name}}' "$container" | sed 's/^\///')
            printf " Starting container ($container_counter/$total_containers): $container_name ($container)\n" | tee /proc/1/fd/1 -a "$logfile"
            docker start "$container" > /dev/null 2>&1

            docstate=$(docker inspect -f {{.State.Running}} "$container")
            printf "   Container running state: $docstate\n" | tee /proc/1/fd/1 -a "$logfile"

            if [ "$docstate" == "true" ]; then
                printf "   Container started\n" | tee /proc/1/fd/1 -a "$logfile"
            else
                printf "Container $container_name ($container) still not running, should be started!!!\n" | tee /proc/1/fd/1 -a "$logfile"
            fi
            printf ".....................................................\n" | tee /proc/1/fd/1 -a "$logfile"
        done
    else
        printf "No Docker containers found to start\n" | tee /proc/1/fd/1 -a "$logfile"
    fi

        # Check success and send to Telegram
        if [ $? -eq 0 ]; then
            # If successful, send a notification
            DATE_TIME=$(date +'%Y-%m-%d %H:%M')
            MESSAGE="$Telegram_SUCCESS $DATE_TIME"
        else
            # If unsuccessful, send a notification
            DATE_TIME=$(date +'%Y-%m-%d %H:%M')
            MESSAGE="$Telegram_ERROR $DATE_TIME"
        fi
        curl -s -X POST "https://api.telegram.org/bot$Telegram_TOKEN/sendMessage" -d "chat_id=$Telegram_CHAT_ID&text=Docker containers are started $MESSAGE"

    printf "Script stopped: $(date)\n" | tee /proc/1/fd/1 -a "$logfile"
    printf "$separator\n" | tee /proc/1/fd/1 -a "$logfile"
fi


here is a new version of the script, pls don’t forget to specify the the parameters with the comment - # replace …

#!/bin/bash
### GLOBAL VARIABLES ####
###https://duplicati.readthedocs.io/en/latest/appendix-g-example-scripts/#run-script-examplesh
###############################################################################
# We read a few variables first.
EVENTNAME=$DUPLICATI__EVENTNAME
OPERATIONNAME=$DUPLICATI__OPERATIONNAME
REMOTEURL=$DUPLICATI__REMOTEURL
today=$(date +"%Y-%m-%d")
Telegram_TOKEN="YUOR_Telegram_TOKEN" # replace 'YUOR_Telegram_TOKEN' with your Telegram_TOKEN
Telegram_CHAT_ID="YUOR_Telegram_CHAT_ID" # replace 'YUOR_Telegram_CHAT_ID' with your Telegram_CHAT_ID
Telegram_SUCCESS="✅"
Telegram_ERROR="💥🔴"
#Telegram_WARN="🟡"
today=$(date +"%Y-%m-%d")
LOGS_FOLDER="YOUR_FOLDER/myLogs/duplicati" # replace 'YOUR_FOLDER' with the path you would like to store logs logs e.x. '/home/pi'
# Get duplicati script event: BEFORE/AFTER
dupevent=${DUPLICATI__EVENTNAME}
# Get duplicati operation event: "Backup", "Cleanup", "Restore", or "DeleteAllButN"
dupopevent=${DUPLICATI__OPERATIONNAME}
# logfile
logfile="$LOGS_FOLDER/duplicati_script_before_after_$today.log" 

# Create folder for logs if don't exist 
if [ ! -d "$LOGS_FOLDER" ]; then
    mkdir -p "$LOGS_FOLDER"
fi

# logging
log() {
    echo "$(date +"%Y-%m-%d %H:%M:%S") $1" >> "$logfile"
}

# send to Telegram
send_telegram_message() {
    local message="$1"
    curl -s -X POST "https://api.telegram.org/bot$Telegram_TOKEN/sendMessage" -d "chat_id=$Telegram_CHAT_ID&text=$message"
}

# Stop Docker containers
stop_docker_containers() {
    log "Stopping Docker containers"
    docker ps -q | while read -r container; do
        local container_name=$(docker inspect --format '{{.Name}}' "$container" | sed 's/^\///')
        log "Stopping container: $container_name ($container)"
        docker stop "$container" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            log "Container stopped: $container_name"
            echo "$container" >> "$started_containers_file" # write down stopped containers
        else
            log "Failed to stop container: $container_name"
        fi
    done
}

# start Docker containers
start_docker_containers() {
    log "Starting Docker containers"
    cat "$started_containers_file" | while read -r container; do
        local container_name=$(docker inspect --format '{{.Name}}' "$container" | sed 's/^\///')
        log "Starting container: $container_name ($container)"
        docker start "$container" > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            log "Container started: $container_name"
        else
            log "Failed to start container: $container_name"
        fi
    done
}

# Check if the file exist started_containers_file, if no - create it 
# List to keep track of container states
started_containers_file='$LOGS_FOLDER/started_containers_$today.txt'
if [ ! -f "$started_containers_file" ]; then
    touch "$started_containers_file"
fi

if [ "$dupopevent" == "Backup" ]; then
    event_name=" ${dupopevent} \"${DUPLICATI__backup_name}\""
    separator_length=$(( ${#event_name} + 1 ))
    separator=$(printf '=%.0s' $(seq 1 $separator_length))
    printf "\n$separator\n$event_name\n$separator\n" >> "$logfile"
    printf "Script start: $(date)\n" >> "$logfile"
    printf "Duplicati event: ${dupevent}\n" >> "$logfile"

    if [ "$dupevent" == "BEFORE" ]; then
        printf "Duplicati running BEFORE event script\n" >> "$logfile"
        printf "Found $(docker ps -aq | wc -l) Docker containers\n" >> "$logfile"
        stop_docker_containers
        send_telegram_message "Duplicati: Docker containers are stopped"
    elif [ "$dupevent" == "AFTER" ]; then
        printf "Duplicati running AFTER event script\n" >> "$logfile"
        printf "Found $(cat "$started_containers_file" | wc -l) Docker containers to start\n" >> "$logfile"
        start_docker_containers
        send_telegram_message "Duplicati: Docker containers are started"
    fi

    printf "Script stopped: $(date)\n" >> "$logfile"
    printf "$separator\n" >> "$logfile"
fi