{"id":62,"date":"2025-11-28T16:14:19","date_gmt":"2025-11-29T00:14:19","guid":{"rendered":"https:\/\/rainier-it.com\/blog\/?p=62"},"modified":"2025-11-28T17:36:15","modified_gmt":"2025-11-29T01:36:15","slug":"create-a-backup-script-for-the-home-directory","status":"publish","type":"post","link":"https:\/\/rainier-it.com\/blog\/create-a-backup-script-for-the-home-directory\/","title":{"rendered":"Create a Backup Script for the \/home Directory"},"content":{"rendered":"\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>When I first started using Gemini, version 2, I prompted a very simple, not much context &#8220;one shot prompt&#8221;: &#8220;Create a bash script that backs up the \/home directory. Give it all the bells and whistles.&#8221;<\/p>\n\n\n\n<p>And the AI responded, of course: &#8220;Of course. Here is a comprehensive bash script to back up your <code>\/home<\/code> directory, complete with features for robust and automated use.&#8221; <\/p>\n\n\n\n<p>And proceeded to give me this:<\/p>\n\n\n\n<p>&#8220;Here is the complete, polished guide designed for publication. It includes the robust backup script (with the standard <code>gzip<\/code> you requested), updated with <code>rsync<\/code> capabilities, and clear, beginner-friendly instructions on how to set up the necessary SSH keys.&#8221;<\/p>\n\n\n\n<p>Alright, I did more than one shot and added a little extra functionality&#8230;enjoy!  ~Christopher<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">\ud83d\udee1\ufe0f The Ultimate Automated Offsite Backup Guide<\/h1>\n\n\n\n<p>This guide will help you set up a professional-grade backup system for your Linux <code>\/home<\/code> directory. It creates a compressed archive, checks for disk space, keeps your local drive clean, and\u2014most importantly\u2014<strong>automatically syncs everything to a remote server<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccb Prerequisites<\/h2>\n\n\n\n<p>Before using the script, you need two things:<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>A Remote Server:<\/strong> Another computer or VPS (like AWS, DigitalOcean, or a friend&#8217;s house) with SSH access.<\/li>\n\n\n\n<li><strong>SSH Keys:<\/strong> The script needs to log in to the remote server without typing a password.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd11 Setting up Password-less SSH (Do this first!)<\/h3>\n\n\n\n<p>Run these commands on the <strong>source computer<\/strong> (the one you are backing up):<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li><strong>Generate a generic key pair (if you haven&#8217;t already):<\/strong> <code>ssh-keygen -t rsa -b 4096 # Press Enter through all prompts. Do NOT set a passphrase for this key.<\/code><\/li>\n\n\n\n<li>Copy the key to your remote server:Replace user and remote_server_ip with your actual details. <code>ssh-copy-id user@remote_server_ip<\/code><\/li>\n\n\n\n<li>Test it: Type <code>ssh user@remote_server_ip<\/code>. If it logs you in without asking for a password, you are ready to rock! \ud83c\udfb8<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udcdc The Script<\/h2>\n\n\n\n<p>Save this code as <code>\/usr\/local\/sbin\/backup_home.sh<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>#!\/bin\/bash\n\n# #############################################################################\n#\n# \ud83d\udee1\ufe0f ROBUST OFFSITE BACKUP SCRIPT\n#\n# Features:\n#   - Backs up \/home to a local directory.\n#   - Standard Gzip compression (universal compatibility).\n#   - Checks for disk space before starting.\n#   - auto-cleans old local backups.\n#   - SYNCs backups to a remote server via Rsync\/SSH.\n#\n# #############################################################################\n\n# ==============================================================================\n# \u2699\ufe0f CONFIGURATION\n# ==============================================================================\n\n# --- LOCAL SETTINGS ---\n# Where to store files locally before sending them offsite.\nBACKUP_DEST=\"\/backups\/home\"\nSOURCE_DIR=\"\/home\"\n# How many days to keep backups locally.\nRETENTION_DAYS=7\n# Disk space safety margin (1.2 = 20% buffer).\nREQUIRED_SPACE_MARGIN=1.2\n# Exclude file path.\nEXCLUDE_FILE=\"\/etc\/backup_home_exclude.txt\"\n\n# --- REMOTE SERVER SETTINGS ---\n# Set to \"true\" to enable offsite syncing.\nENABLE_OFFSITE=\"true\"\n# Your remote username.\nREMOTE_USER=\"REPLACE_WITH_REMOTE_USERNAME\"\n# Your remote server IP or Hostname.\nREMOTE_HOST=\"REPLACE_WITH_REMOTE_IP_OR_DOMAIN\"\n# The path on the remote server where backups should go.\nREMOTE_DIR=\"\/home\/REPLACE_WITH_REMOTE_USERNAME\/backups\"\n# Path to your private SSH key (usually \/root\/.ssh\/id_rsa or \/home\/user\/.ssh\/id_rsa).\nSSH_KEY_PATH=\"\/root\/.ssh\/id_rsa\"\n\n\n# ==============================================================================\n# \ud83d\udd12 INTERNAL VARIABLES &amp; FUNCTIONS\n# ==============================================================================\n\nSCRIPT_NAME=$(basename \"$0\")\nTIMESTAMP=$(date +\"%Y-%m-%d_%H-%M-%S\")\nBACKUP_FILENAME=\"home-backup-${TIMESTAMP}.tar.gz\"\nBACKUP_FILE_PATH=\"${BACKUP_DEST}\/${BACKUP_FILENAME}\"\nLOG_FILE=\"${BACKUP_DEST}\/backup_log.log\"\n\nlog_message() {\n    echo \"$(date +\"%Y-%m-%d %H:%M:%S\") - ${SCRIPT_NAME} - $1\"\n}\n\nhandle_error() {\n    log_message \"\u274c ERROR: $1\"\n    exit \"${2:-1}\"\n}\n\ncleanup_old_backups() {\n    log_message \"\ud83e\uddf9 Cleaning up local backups older than ${RETENTION_DAYS} days...\"\n    find \"${BACKUP_DEST}\" -name \"home-backup-*.tar.gz\" -mtime +\"$((RETENTION_DAYS - 1))\" -print0 |\n    while IFS= read -r -d '' line; do\n        log_message \"   -> Deleting: ${line}\"\n        rm \"${line}\"\n    done\n}\n\n# Redirect output to Screen AND Log File\nexec &amp;> >(tee -a \"${LOG_FILE}\")\n\nlog_message \"============================================================\"\nlog_message \"\ud83d\ude80 Starting Backup Process\"\nlog_message \"============================================================\"\n\n# 1. Pre-flight Checks\n# --------------------\nif [&#91; \"${EUID}\" -ne 0 &#93;]; then\n    handle_error \"Script must be run as root.\"\nfi\n\n# Create local destination\nif [&#91; ! -d \"${BACKUP_DEST}\" &#93;]; then\n    mkdir -p \"${BACKUP_DEST}\" || handle_error \"Failed to create local backup dir.\"\nfi\n\n# Create exclude file if missing\nif [&#91; ! -f \"${EXCLUDE_FILE}\" &#93;]; then\n    log_message \"\u26a0\ufe0f Creating empty exclude file at ${EXCLUDE_FILE}\"\n    touch \"${EXCLUDE_FILE}\"\nfi\n\n# Disk Space Check\nlog_message \"\ud83d\udd0e Checking local disk space...\"\nSOURCE_SIZE=$(du -sb \"${SOURCE_DIR}\" | awk '{print $1}')\nREQ_SPACE=$(echo \"${SOURCE_SIZE} * ${REQUIRED_SPACE_MARGIN}\" | bc | cut -d'.' -f1)\nAVAIL_SPACE=$(df --output=avail \"${BACKUP_DEST}\" | tail -n 1)\n\nif (( AVAIL_SPACE &lt; REQ_SPACE )); then\n    REQ_HR=$(numfmt --to=iec --format=\"%.1f\" \"${REQ_SPACE}\")\n    AVAIL_HR=$(df -h \"${BACKUP_DEST}\" | awk 'NR==2{print $4}')\n    handle_error \"Insufficient Space. Needed: ~${REQ_HR}. Available: ${AVAIL_HR}.\"\nfi\nlog_message \"\u2705 Disk space OK.\"\n\n\n# 2. The Backup\n# -------------\nlog_message \"\ud83d\udce6 creating archive: ${BACKUP_FILENAME}...\"\n\nionice -c 3 nice -n 19 tar \\\n    --exclude-from=\"${EXCLUDE_FILE}\" \\\n    --one-file-system \\\n    -cvzpf \"${BACKUP_FILE_PATH}\" \\\n    \"${SOURCE_DIR}\"\n\nif [&#91; $? -eq 0 &#93;]; then\n    SIZE=$(du -sh \"${BACKUP_FILE_PATH}\" | awk '{print $1}')\n    log_message \"\u2705 Local backup created successfully (${SIZE}).\"\n    cleanup_old_backups\nelse\n    rm -f \"${BACKUP_FILE_PATH}\"\n    handle_error \"Tar command failed. Temporary file removed.\"\nfi\n\n\n# 3. Offsite Transfer (Rsync)\n# ---------------------------\nif [&#91; \"${ENABLE_OFFSITE}\" == \"true\" &#93;]; then\n    log_message \"\u2601\ufe0f Starting Rsync to ${REMOTE_HOST}...\"\n\n    # The trailing slash on BACKUP_DEST\/ is crucial!\n    # It syncs the CONTENTS of the folder, propagating deletions (mirroring).\n    rsync -avz --delete -e \"ssh -i ${SSH_KEY_PATH} -o StrictHostKeyChecking=no\" \\\n        \"${BACKUP_DEST}\/\" \\\n        \"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}\"\n        \n    if [&#91; $? -eq 0 &#93;]; then\n        log_message \"\u2705 Offsite sync completed successfully.\"\n    else\n        log_message \"\u26a0\ufe0f WARNING: Offsite sync failed. Local backup is safe, but check network\/SSH.\"\n        # We do not exit with error here, because the local backup was a success.\n    fi\nelse\n    log_message \"\u2601\ufe0f Offsite backup disabled in config. Skipping.\"\nfi\n\nlog_message \"\ud83c\udfc1 Process Finished.\"\nlog_message \"============================================================\"\nexit 0\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">#!\/bin\/bash<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># #############################################################################<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># \ud83d\udee1\ufe0f ROBUST OFFSITE BACKUP SCRIPT<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Features:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   - Backs up \/home to a local directory.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   - Standard Gzip compression (universal compatibility).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   - Checks for disk space before starting.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   - auto-cleans old local backups.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#   - SYNCs backups to a remote server via Rsync\/SSH.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">#<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># #############################################################################<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ==============================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># \u2699\ufe0f CONFIGURATION<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ==============================================================================<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># --- LOCAL SETTINGS ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Where to store files locally before sending them offsite.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\/backups\/home<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">SOURCE_DIR<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\/home<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># How many days to keep backups locally.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">RETENTION_DAYS<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #B48EAD\">7<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Disk space safety margin (1.2 = 20% buffer).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">REQUIRED_SPACE_MARGIN<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #B48EAD\">1.2<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Exclude file path.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">EXCLUDE_FILE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\/etc\/backup_home_exclude.txt<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># --- REMOTE SERVER SETTINGS ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Set to &quot;true&quot; to enable offsite syncing.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">ENABLE_OFFSITE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">true<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Your remote username.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">REMOTE_USER<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">REPLACE_WITH_REMOTE_USERNAME<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Your remote server IP or Hostname.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">REMOTE_HOST<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">REPLACE_WITH_REMOTE_IP_OR_DOMAIN<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># The path on the remote server where backups should go.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">REMOTE_DIR<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\/home\/REPLACE_WITH_REMOTE_USERNAME\/backups<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Path to your private SSH key (usually \/root\/.ssh\/id_rsa or \/home\/user\/.ssh\/id_rsa).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">SSH_KEY_PATH<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\/root\/.ssh\/id_rsa<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ==============================================================================<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># \ud83d\udd12 INTERNAL VARIABLES &amp; FUNCTIONS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ==============================================================================<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">SCRIPT_NAME<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">basename<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9\">$0<\/span><span style=\"color: #ECEFF4\">&quot;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">TIMESTAMP<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">date<\/span><span style=\"color: #A3BE8C\"> +<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">%Y-%m-%d_%H-%M-%S<\/span><span style=\"color: #ECEFF4\">&quot;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">BACKUP_FILENAME<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">home-backup-<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">TIMESTAMP<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">.tar.gz<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">BACKUP_FILE_PATH<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">\/<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_FILENAME<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">LOG_FILE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">\/backup_log.log<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">echo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;$(<\/span><span style=\"color: #88C0D0\">date<\/span><span style=\"color: #A3BE8C\"> +<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">%Y-%m-%d %H:%M:%S<\/span><span style=\"color: #ECEFF4\">&quot;)<\/span><span style=\"color: #A3BE8C\"> - <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SCRIPT_NAME<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\"> - <\/span><span style=\"color: #D8DEE9\">$1<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">handle_error<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u274c ERROR: <\/span><span style=\"color: #D8DEE9\">$1<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">exit<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9\">${2<\/span><span style=\"color: #81A1C1\">:-<\/span><span style=\"color: #D8DEE9\">1}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">cleanup_old_backups<\/span><span style=\"color: #ECEFF4\">()<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\ud83e\uddf9 Cleaning up local backups older than <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">RETENTION_DAYS<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\"> days...<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">find<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-name<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">home-backup-*.tar.gz<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-mtime<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">+<\/span><span style=\"color: #ECEFF4\">&quot;$((<\/span><span style=\"color: #A3BE8C\">RETENTION_DAYS <\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">))&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-print0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">|<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">while<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">IFS<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">read<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-r<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-d<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#39;&#39;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">line<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">do<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">   -&gt; Deleting: <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">line<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">rm<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">line<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">done<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Redirect output to Screen AND Log File<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">exec<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&amp;<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&gt;(<\/span><span style=\"color: #88C0D0\">tee<\/span><span style=\"color: #A3BE8C\"> -a <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">LOG_FILE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">============================================================<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\ud83d\ude80 Starting Backup Process<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">============================================================<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># 1. Pre-flight Checks<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># --------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">EUID<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-ne<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">handle_error<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Script must be run as root.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Create local destination<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-d<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">mkdir<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-p<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">||<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">handle_error<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Failed to create local backup dir.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Create exclude file if missing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">!<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">EXCLUDE_FILE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u26a0\ufe0f Creating empty exclude file at <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">EXCLUDE_FILE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">touch<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">EXCLUDE_FILE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># Disk Space Check<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\ud83d\udd0e Checking local disk space...<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">SOURCE_SIZE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">du<\/span><span style=\"color: #A3BE8C\"> -sb <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SOURCE_DIR<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">awk<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">{print $1}<\/span><span style=\"color: #ECEFF4\">&#39;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">REQ_SPACE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">echo<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SOURCE_SIZE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\"> * <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REQUIRED_SPACE_MARGIN<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">bc<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">cut<\/span><span style=\"color: #A3BE8C\"> -d<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">.<\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\"> -f1<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">AVAIL_SPACE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">df<\/span><span style=\"color: #A3BE8C\"> --output=avail <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">tail<\/span><span style=\"color: #A3BE8C\"> -n <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">((<\/span><span style=\"color: #D8DEE9FF\"> AVAIL_SPACE <\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9FF\"> REQ_SPACE <\/span><span style=\"color: #ECEFF4\">))<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">REQ_HR<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">numfmt<\/span><span style=\"color: #A3BE8C\"> --to=iec --format=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">%.1f<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REQ_SPACE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">AVAIL_HR<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">df<\/span><span style=\"color: #A3BE8C\"> -h <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">awk<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">NR==2{print $4}<\/span><span style=\"color: #ECEFF4\">&#39;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">handle_error<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Insufficient Space. Needed: ~<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REQ_HR<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">. Available: <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">AVAIL_HR<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u2705 Disk space OK.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># 2. The Backup<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># -------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\ud83d\udce6 creating archive: <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_FILENAME<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">...<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">ionice<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-c<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">nice<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-n<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">19<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">tar<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #A3BE8C\">--exclude-from=<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">EXCLUDE_FILE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #A3BE8C\">--one-file-system<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #A3BE8C\">-cvzpf<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_FILE_PATH<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SOURCE_DIR<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$?<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-eq<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">SIZE<\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #ECEFF4\">$(<\/span><span style=\"color: #88C0D0\">du<\/span><span style=\"color: #A3BE8C\"> -sh <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_FILE_PATH<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #81A1C1\">|<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #88C0D0\">awk<\/span><span style=\"color: #A3BE8C\"> <\/span><span style=\"color: #ECEFF4\">&#39;<\/span><span style=\"color: #A3BE8C\">{print $1}<\/span><span style=\"color: #ECEFF4\">&#39;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u2705 Local backup created successfully (<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SIZE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">).<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">cleanup_old_backups<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">rm<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-f<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_FILE_PATH<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">handle_error<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Tar command failed. Temporary file removed.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># 3. Offsite Transfer (Rsync)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\"># ---------------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">ENABLE_OFFSITE<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">==<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">true<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u2601\ufe0f Starting Rsync to <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REMOTE_HOST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">...<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #616E88\"># The trailing slash on BACKUP_DEST\/ is crucial!<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #616E88\"># It syncs the CONTENTS of the folder, propagating deletions (mirroring).<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">rsync<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-avz<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">--delete<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">-e<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">ssh -i <\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">SSH_KEY_PATH<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\"> -o StrictHostKeyChecking=no<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">BACKUP_DEST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">\/<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #EBCB8B\">\\<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REMOTE_USER<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">@<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REMOTE_HOST<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #A3BE8C\">:<\/span><span style=\"color: #81A1C1\">${<\/span><span style=\"color: #D8DEE9\">REMOTE_DIR<\/span><span style=\"color: #81A1C1\">}<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">[&#91;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">$?<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">-eq<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&#93;]<\/span><span style=\"color: #81A1C1\">;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">then<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u2705 Offsite sync completed successfully.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u26a0\ufe0f WARNING: Offsite sync failed. Local backup is safe, but check network\/SSH.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #616E88\"># We do not exit with error here, because the local backup was a success.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">else<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\u2601\ufe0f Offsite backup disabled in config. Skipping.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">fi<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">\ud83c\udfc1 Process Finished.<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">log_message<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">============================================================<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">exit<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udee0\ufe0f Installation Instructions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Install Dependencies<\/h3>\n\n\n\n<p>You need <code>bc<\/code> (for math calculations) and <code>rsync<\/code> (for the transfer):<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sudo apt update\nsudo apt install bc rsync\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">apt<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">update<\/span><\/span>\n<span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">apt<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">install<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">bc<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">rsync<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">2. Create the Script<\/h3>\n\n\n\n<p>Open your favorite text editor:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sudo vim \/usr\/local\/sbin\/backup_home.sh\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">vim<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">\/usr\/local\/sbin\/backup_home.sh<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Paste the code from above into this file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Edit Your Settings<\/h3>\n\n\n\n<p>Scroll to the <strong>CONFIGURATION<\/strong> section at the top of the script.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Update<\/strong> <code>REMOTE_USER<\/code> (e.g., <code>root<\/code> or <code>john<\/code>).<\/li>\n\n\n\n<li><strong>Update<\/strong> <code>REMOTE_HOST<\/code> (e.g., <code>192.168.1.50<\/code> or <code>myserver.com<\/code>).<\/li>\n\n\n\n<li><strong>Update<\/strong> <code>SSH_KEY_PATH<\/code>. If you are running this script as root (which you should), your key is likely at <code>\/root\/.ssh\/id_rsa<\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. Make it Executable<\/h3>\n\n\n\n<p>Give the script permission to run:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sudo chmod +x \/usr\/local\/sbin\/backup_home.sh\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">chmod<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">+x<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">\/usr\/local\/sbin\/backup_home.sh<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">5. Create the Exclude File<\/h3>\n\n\n\n<p>Tell the backup what to ignore (Temporary files, Cache, Trash):<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sudo vim \/etc\/backup_home_exclude.txt\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">vim<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">\/etc\/backup_home_exclude.txt<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><em>Paste this recommended list:<\/em><\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>*\/.cache\n*\/.local\/share\/Trash\n*\/Downloads\n*.tmp\n*.log\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">\/.cache<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">\/.local\/share\/Trash<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">\/Downloads<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">.tmp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\">.log<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">6. Run a Test<\/h3>\n\n\n\n<p>Run it manually to watch the magic happen:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>sudo \/usr\/local\/sbin\/backup_home.sh\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">sudo<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #A3BE8C\">\/usr\/local\/sbin\/backup_home.sh<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u23f0 Automate with Cron<\/h2>\n\n\n\n<p>Once your test run is successful, set it to run automatically every night at 3:00 AM.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>Open the root crontab: <code>sudo crontab -e<\/code><\/li>\n\n\n\n<li>Paste this line at the bottom: <code>0 3 * * * \/usr\/local\/sbin\/backup_home.sh<\/code><\/li>\n<\/ol>\n\n\n\n<p><strong>You&#8217;re done!<\/strong> Your system will now back up locally, clean up old files, and sync the changes to your offsite server automatically.<\/p>\n\n\n\n<p>Give this a read\/rewrite and\/or a test, and tell me what you think. This has actually been one of the first things I run when testing out a new AI tool, with and without context. Next time we will see what Claude will do for us.<\/p>\n\n\n\n<p>Thanks!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I first started using Gemini, version 2, I prompted a very simple, not much context &#8220;one shot prompt&#8221;: &#8220;Create a bash script that backs [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":68,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,10],"tags":[13,12,14],"class_list":["post-62","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices","category-linux","tag-backthatup","tag-linux-2","tag-terminal"],"_links":{"self":[{"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/posts\/62","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/comments?post=62"}],"version-history":[{"count":10,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/posts\/62\/revisions"}],"predecessor-version":[{"id":75,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/posts\/62\/revisions\/75"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/media\/68"}],"wp:attachment":[{"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/media?parent=62"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/categories?post=62"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rainier-it.com\/blog\/wp-json\/wp\/v2\/tags?post=62"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}