|
#!/bin/bash |
|
|
|
# Function to display help message |
|
display_help() { |
|
echo "Usage: $0 [OPTION]..." |
|
echo "Install and setup automated backup to SMB." |
|
echo |
|
echo " -s, --source Source directory for backup (required)" |
|
echo " -i, --ip SMB server IP (required)" |
|
echo " -n, --share SMB share name (required)" |
|
echo " -u, --username SMB username (required)" |
|
echo " -p, --password SMB password (required)" |
|
echo " -w, --webhook Discord webhook URL (required)" |
|
echo " -r, --prune Days after which to prune old backups (default is 30)" |
|
echo " -c, --cron Crontab schedule expression (default is '0 3 * * *' for 3 AM daily)" |
|
echo " -b, --bwlimit Bandwidth limit in KB/s (default is 12500 for 100 Mbit/s)" |
|
echo " -h, --help Display this help and exit" |
|
exit 1 |
|
} |
|
|
|
# Default values |
|
PRUNE_DAYS=30 |
|
CRON_SCHEDULE="0 3 * * *" |
|
BWLIMIT=12500 # Default bandwidth limit is 100 Mbit/s or 12500 KB/s |
|
|
|
# Parse named arguments |
|
while [[ "$#" -gt 0 ]]; do |
|
case $1 in |
|
-s|--source) SOURCE_DIR="$2"; shift ;; |
|
-i|--ip) SMB_IP="$2"; shift ;; |
|
-n|--share) SHARE_NAME="$2"; shift ;; |
|
-u|--username) SMB_USERNAME="$2"; shift ;; |
|
-p|--password) SMB_PASSWORD="$2"; shift ;; |
|
-w|--webhook) DISCORD_WEBHOOK="$2"; shift ;; |
|
-r|--prune) PRUNE_DAYS="$2"; shift ;; |
|
-c|--cron) CRON_SCHEDULE="$2"; shift ;; |
|
-b|--bwlimit) BWLIMIT="$2"; shift ;; |
|
-h|--help) display_help ;; |
|
*) echo "Unknown parameter passed: $1"; exit 1 ;; |
|
esac |
|
shift |
|
done |
|
|
|
# Check for required parameters |
|
if [ -z "$SOURCE_DIR" ] || [ -z "$SMB_IP" ] || [ -z "$SHARE_NAME" ] || [ -z "$SMB_USERNAME" ] || [ -z "$SMB_PASSWORD" ] || [ -z "$DISCORD_WEBHOOK" ]; then |
|
display_help |
|
fi |
|
|
|
# Install SMB Client |
|
sudo apt-get update |
|
sudo apt-get install -y cifs-utils |
|
|
|
# Create SMB credentials file in a secure location |
|
CREDENTIALS_FILE="/etc/smb_credentials" |
|
echo "username=${SMB_USERNAME}" | sudo tee $CREDENTIALS_FILE > /dev/null |
|
echo "password=${SMB_PASSWORD}" | sudo tee -a $CREDENTIALS_FILE > /dev/null |
|
# Secure the file |
|
sudo chmod 600 $CREDENTIALS_FILE |
|
|
|
LOG_FILE="/var/log/backup_to_smb.log" |
|
|
|
# Create the backup script |
|
cat << EOL > ~/backup_to_smb.sh |
|
#!/bin/bash |
|
|
|
TARGET_DIR="/mnt/smb_share" |
|
LOG_FILE="/var/log/backup_to_smb.log" |
|
RUN_ID=\$(uuidgen) |
|
|
|
# Ensure log file exists |
|
touch \$LOG_FILE |
|
|
|
# Check if the share is already mounted |
|
if ! mountpoint -q \$TARGET_DIR; then |
|
# Mount the SMB share |
|
mkdir -p \$TARGET_DIR |
|
sudo mount -t cifs //${SMB_IP}/${SHARE_NAME} \$TARGET_DIR -o credentials=${CREDENTIALS_FILE} |
|
if [ \$? -ne 0 ]; then |
|
echo "\$(date -u +'%Y-%m-%dT%H:%M:%SZ') - Run ID: \$RUN_ID - Failed to mount SMB share" >> \$LOG_FILE |
|
curl -X POST -H "Content-Type: application/json" -d "{\"content\": \"❌ Failed to mount SMB share.\"}" ${DISCORD_WEBHOOK} |
|
exit 1 |
|
fi |
|
fi |
|
|
|
# Notification on start |
|
curl -X POST -H "Content-Type: application/json" -d '{"content": "🏁 Backup to SMB started."}' ${DISCORD_WEBHOOK} |
|
|
|
START_TIME=\$(date -u +%s) |
|
|
|
# Backup using rsync. Only backup files which are younger than the prune value. |
|
TMP_FILE_LIST="/tmp/files_to_backup.txt" |
|
find $SOURCE_DIR -type f -mtime -$PRUNE_DAYS > \$TMP_FILE_LIST |
|
rsync -avz --no-relative --bwlimit=$BWLIMIT --files-from=\$TMP_FILE_LIST / \$TARGET_DIR |
|
rm -f \$TMP_FILE_LIST |
|
|
|
# Check if rsync completed successfully |
|
if [ \$? -ne 0 ]; then |
|
echo "\$(date -u +'%Y-%m-%dT%H:%M:%SZ') - Run ID: \$RUN_ID - Rsync failed" >> $LOG_FILE |
|
curl -X POST -H "Content-Type: application/json" -d '{"content": "❌ Backup to SMB failed!"}' ${DISCORD_WEBHOOK} |
|
fi |
|
|
|
END_TIME=\$(date -u +%s) |
|
DURATION=\$((END_TIME - START_TIME)) |
|
|
|
# Notification on successful completion |
|
curl -X POST -H "Content-Type: application/json" -d '{"content": "💾 Backup to SMB completed in '\$DURATION' seconds."}' ${DISCORD_WEBHOOK} |
|
|
|
# Prune old backups, excluding .lock files |
|
find \$TARGET_DIR -mtime +$PRUNE_DAYS -type f ! -name '*.lock' -delete |
|
|
|
# Unmount the SMB share |
|
sudo umount \$TARGET_DIR |
|
|
|
# Prune the log file to keep it under 50MB |
|
tail -c 50M $LOG_FILE > \$LOG_FILE.tmp |
|
mv \$LOG_FILE.tmp $LOG_FILE |
|
EOL |
|
|
|
sudo chmod +x ~/backup_to_smb.sh |
|
|
|
# Check if the cron job already exists |
|
CRON_EXISTING=$(crontab -l | grep "~/backup_to_smb.sh") |
|
|
|
# Schedule the backup only if it's not already there |
|
if [ -z "$CRON_EXISTING" ]; then |
|
(crontab -l 2>/dev/null; echo "$CRON_SCHEDULE ~/backup_to_smb.sh") | crontab - |
|
fi |
|
|
|
echo "Installation and setup complete." |