Hey guys. I found wolfv's excellent script for rclone here "wolfv Backup script". First of all, thank you so much for it. I love it! I wrote a little one myself to stop running docker containers so I could backup the appdate folder from my unraid server without interference.
It's my first bash script ever. So I'm sure there's plenty of room for improvement. But maybe it will serve as a suggestion for one or the other. Or maybe wolfv would like to implement such a feature in his script. I don't know how to send it to him, though, since the thread is already closed.
As I'm very inexperienced with bash scripts, I can't guarantee that it will work. So use it at your own risk However, it has worked for me for a while without any problems. There is also a hint where you can add your own exception handling.
Function: First, certain containers are stopped in a certain order. Then all the others that are currently running. Then wolf's script can be executed. Then the stopped containers are started again.
#!/bin/bash
log_path="./logfile.log" # Path to the log file
# Function to write log messages
log() {
echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$log_path"
}
# Log file header
log "Script started."
# List of containers to stop first
docker_first=("Nextcloud" "MariaDB")
# Get the list of currently running containers
docker_result=$(docker container ls -q)
# List of containers to start last
docker_last=("MariaDB" "Nextcloud")
# Function to execute container stop/start commands
execute_containers() {
local command="$1" # Stop or start command
shift
local containers=("$@") # Containers to stop/start
local failed_containers=() # Array to store containers that fail to stop/start
for con in "${containers[@]}"; do
log "Stopping $con ..."
docker "$command" "$con"
# Wait for container to stop/start within a timeout period
local timeout=30
local interval=5
local elapsed=0
while true; do
container_status=$(docker inspect -f '{{.State.Status}}' "$con")
if [[ "$command" == "start" ]]; then
status="running"
else
status="exited"
fi
if [[ "$container_status" == "$status" ]]; then
log "$con has successfully changed its status"
break
fi
if (( elapsed >= timeout )); then
log "Timeout: Container $con failed to $command"
failed_containers+=("$con")
break
fi
sleep "$interval"
elapsed=$((elapsed + interval))
done
sleep 5
done
if [[ ${#failed_containers[@]} -gt 0 ]]; then
log "Failed to $command the following containers: ${failed_containers[*]}"
# Additional actions or error handling for containers that fail to stop/start
fi
}
# Stop the containers listed in docker_first array
execute_containers "stop" "${docker_first[@]}"
log "Done stopping"
# Convert the docker_result string into an array
IFS=$'\n' read -rd '' -a containers <<< "$docker_result"
# Stop the remaining containers
execute_containers "stop" "${containers[@]}"
log "Done stopping remaining containers"
# Start the containers listed in docker_last array
execute_containers "start" "${docker_last[@]}"
log "Done starting"
# Start the remaining containers
execute_containers "start" "${containers[@]}"
log "Done starting remaining containers"
# Log file footer
log "Script completed."