From 477f96dcf12d3a81827bb56d9a11ef9a57969485 Mon Sep 17 00:00:00 2001 From: Tomi Eckert Date: Sat, 30 Aug 2025 13:23:28 +0200 Subject: [PATCH] add tomi.sh --- tomi.sh | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 tomi.sh diff --git a/tomi.sh b/tomi.sh new file mode 100644 index 0000000..b12d067 --- /dev/null +++ b/tomi.sh @@ -0,0 +1,221 @@ +#!/bin/bash +# +# Script to backup (export), restore (import), or restore-and-rename a SAP HANA schema. +# It automatically detects the number of available CPU threads to optimize operations. +# Designed for both interactive use and cronjob automation. +# +# ETomi 2025 + +# --- Configuration --- +hdbsql_path="/usr/sap/hdbclient/hdbsql" + +# -- HANA Secure User Store Key -- +user_key="CRONKEY" + +# --- Validation --- +for cmd in hdbsql hdbuserstore tar gzip nproc pv mkdir chmod date; do + tool_path="$(dirname "$hdbsql_path")/$cmd" + if ! command -v $cmd &> /dev/null && [ ! -f "$tool_path" ]; then + echo "❌ Error: Required command '$cmd' is not found in your PATH or at '$tool_path'." + exit 1 + fi +done + +if [ "$#" -lt 2 ]; then + echo "❌ Error: Not enough arguments." + echo "" + echo "Usage: $0 " + echo "" + echo "Actions:" + echo " setup-key - Interactively create a secure user store key" + echo " backup [--compress] [--timestamp] - Export a schema, optionally compress and/or add a timestamp" + echo " restore - Import a schema from a path" + echo " restore-rename - Import and rename a schema" + exit 1 +fi + +action=$1 +threads=$(nproc --all) + +# --- Functions --- +confirm_action() { + if [ "$TERM" != "dumb" ] && [ -t 0 ]; then + read -p "❓ Are you sure you want to proceed with the '$1' operation? (y/n): " -n 1 -r + echo "" + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "🛑 Operation cancelled by user." + exit 1 + fi + fi +} + +execute_sql() { + local command_to_run=$1 + local action_name=$2 + + echo "âš™ī¸ Executing SQL: $command_to_run" + $hdbsql_path -U $user_key "$command_to_run" + + if [ $? -ne 0 ]; then + echo "❌ Failure! The '$action_name' command failed. Please check the logs." + exit 1 + fi +} + +# --- Main Logic --- +# The setup-key action is handled first as it doesn't need all global variables. +if [ "$action" == "setup-key" ]; then + if [ "$#" -ne 2 ]; then + echo "❌ Error: Invalid arguments for 'setup-key'." + echo "Usage: $0 setup-key " + exit 1 + fi + key_name=$2 + hdbuserstore_path="$(dirname "$hdbsql_path")/hdbuserstore" + + echo "--- Interactive Secure User Store Key Setup ---" + read -p "Enter HANA host [localhost]: " hdb_host + hdb_host=${hdb_host:-localhost} + + read -p "Enter instance number [00]: " hdb_instance + hdb_instance=${hdb_instance:-00} + hdb_port="3${hdb_instance}15" + + read -p "Enter tenant database name [NDB]: " hdb_tenant + hdb_tenant=${hdb_tenant:-NDB} + + read -p "Enter database user [SYSTEM]: " hdb_user + hdb_user=${hdb_user:-SYSTEM} + + read -sp "Enter password for '$hdb_user': " hdb_pass + echo "" + if [ -z "$hdb_pass" ]; then + echo "❌ Error: Password cannot be empty." + exit 1 + fi + + connection_string="${hdb_host}:${hdb_port}@${hdb_tenant}" + echo "-------------------------------------" + echo "Key Name: $key_name" + echo "Connection String: $connection_string" + echo "Database User: $hdb_user" + echo "-------------------------------------" + confirm_action "create key '$key_name'" + + echo "â–ļī¸ Creating secure store key..." + $hdbuserstore_path SET "$key_name" "$connection_string" "$hdb_user" "$hdb_pass" + + if [ $? -eq 0 ]; then + echo "✅ Success! Key '$key_name' created. You can now set 'user_key=\"$key_name\"' at the top of this script." + else + echo "❌ Failure! Could not create key '$key_name'. Please check the details and try again." + exit 1 + fi + exit 0 +fi + +# --- Actions (Backup/Restore) --- +echo "â„šī¸ Detected $threads available CPU threads to use for the operation." + +case "$action" in + backup) + if [ "$#" -lt 3 ] || [ "$#" -gt 5 ]; then + echo "❌ Error: Invalid arguments for 'backup'." + echo "Usage: $0 backup [--compress] [--timestamp]" + exit 1 + fi + + schema=$2 + path=$3 + compress_flag=false + timestamp_flag=false + + # Loop through optional arguments to handle any order + for arg in "${@:4}"; do + case "$arg" in + --compress) + compress_flag=true + ;; + --timestamp) + timestamp_flag=true + ;; + *) + echo "❌ Error: Invalid option '$arg'. Valid options are '--compress' or '--timestamp'." + exit 1 + ;; + esac + done + + # Add timestamp to path if flag is set + if [ "$timestamp_flag" = true ]; then + timestamp=$(date +'%Y%m%d_%H%M%S') + path="${path}_${timestamp}" + fi + + echo "â„šī¸ Creating backup directory: $path" + mkdir -p "$path" && chmod 777 "$path" + if [ $? -ne 0 ]; then + echo "❌ Failure! Could not create or set permissions for directory '$path'." + exit 1 + fi + + echo "â–ļī¸ Starting BACKUP (EXPORT) for schema '$schema' to '$path'..." + sql_command="EXPORT \"$schema\".\"*\" AS BINARY INTO '$path' WITH REPLACE THREADS $threads;" + execute_sql "$sql_command" "$action" + echo "✅ SQL Export completed successfully." + + if [ "$compress_flag" = true ]; then + echo "â–ļī¸ Compressing backup directory: $path" + archive_file="${path}.tar.gz" + total_size=$(du -sb "$path" | awk '{print $1}') + tar cf - -C "$(dirname "$path")" "$(basename "$path")" | pv -s "$total_size" | gzip > "$archive_file" + if [ $? -eq 0 ]; then + echo "✅ Compression successful: $archive_file" + echo "đŸ—‘ī¸ Removing original backup directory..." + rm -rf "$path" + else + echo "❌ Failure! Compression failed." + exit 1 + fi + fi + ;; + + restore) + if [ "$#" -ne 3 ]; then + echo "❌ Error: Invalid arguments for 'restore'." + echo "Usage: $0 restore " + exit 1 + fi + schema=$2 + path=$3 + confirm_action "restore" + echo "â–ļī¸ Starting RESTORE (IMPORT) for schema '$schema' from '$path'..." + sql_command="IMPORT \"$schema\".\"*\" AS BINARY FROM '$path' WITH IGNORE EXISTING THREADS $threads;" + execute_sql "$sql_command" "$action" + echo "✅ Success! The '$action' operation completed." + ;; + + restore-rename) + if [ "$#" -ne 4 ]; then + echo "❌ Error: Invalid arguments for 'restore-rename'." + echo "Usage: $0 restore-rename " + exit 1 + fi + schema=$2 + new_schema=$3 + path=$4 + confirm_action "restore-rename" + echo "â–ļī¸ Starting RESTORE & RENAME for schema '$schema' from '$path' to '$new_schema'..." + sql_command="IMPORT \"$schema\".\"*\" AS BINARY FROM '$path' WITH IGNORE EXISTING THREADS $threads RENAME SCHEMA \"$schema\" TO \"$new_schema\";" + execute_sql "$sql_command" "$action" + echo "✅ Success! The '$action' operation completed." + ;; + + *) + echo "❌ Error: Invalid action '$action'." + echo "Valid actions are 'backup', 'restore', 'restore-rename', or 'setup-key'." + exit 1 + ;; +esac + +exit 0