demeaning_casually
@demeaning_casually@infosec.pub
- Comment on I wrote a python script to backup my home directory 1 week ago:
No.
It doesn’t really do anything I particularly need.
- Comment on I wrote a python script to backup my home directory 1 week ago:
#!/bin/bash read_settings() { settings_file="$HOME/.config/loci/settings" if [[ -f "$settings_file" ]]; then while IFS='=' read -r key value || [[ -n "$key" ]]; do if [[ ! -z "$key" && ! "$key" =~ ^# && ! "$key" =~ ^\[ ]]; then key=$(echo "$key" | xargs) value=$(echo "$value" | xargs) declare -g "$key"="$value" fi done < "$settings_file" else echo "Settings file not found: $settings_file" exit 1 fi } # Function to perform the backup backup() { local tag="$1" read_settings log_path="$HOME/.backuplog" # Check if header exists in log file, if not, create it if [[ ! -f "$log_path" ]]; then echo "\"tag\",\"timestamp\",\"command\",\"completion_time\"" > "$log_path" elif [[ $(head -1 "$log_path") != "\"tag\",\"timestamp\",\"command\",\"completion_time\"" ]]; then # Add header if it doesn't exist temp_file=$(mktemp) echo "\"tag\",\"timestamp\",\"command\",\"completion_time\"" > "$temp_file" cat "$log_path" >> "$temp_file" mv "$temp_file" "$log_path" fi # Create backup directory if it doesn't exist backup_dest="$backup_root/$tag" mkdir -p "$backup_dest" 2>/dev/null # Rsync command for backup target="$user@$server:/home/$user/$backup_root/$tag" rsync_cmd="rsync -avh $source_dir $target" # If exclude_files is defined and not empty, add it to rsync command if [[ -n "$exclude_files" ]]; then rsync_cmd="rsync -avh --exclude='$exclude_files' $source_dir $target" fi echo "Starting backup for tag '$tag' at $(date '+%Y-%m-%d %H:%M:%S')" echo "Command: $rsync_cmd" # Record start time start_timestamp=$(date +"%Y-%m-%d %H:%M:%S") # Execute the backup eval "$rsync_cmd" backup_status=$? # Record completion time completion_timestamp=$(date +"%Y-%m-%d %H:%M:%S") # Calculate duration start_seconds=$(date -d "$start_timestamp" +%s) end_seconds=$(date -d "$completion_timestamp" +%s) duration=$((end_seconds - start_seconds)) # Format duration if [[ $duration -ge 3600 ]]; then formatted_duration="$((duration / 3600))h $((duration % 3600 / 60))m $((duration % 60))s" elif [[ $duration -ge 60 ]]; then formatted_duration="$((duration / 60))m $((duration % 60))s" else formatted_duration="${duration}s" fi # Log the backup information as proper CSV echo "\"$tag\",\"$start_timestamp\",\"$rsync_cmd\",\"$completion_timestamp\"" >> "$log_path" if [[ $backup_status -eq 0 ]]; then echo -e "\e[32mBackup for '$tag' completed successfully\e[0m" echo "Duration: $formatted_duration" echo "Logged to: $log_path" else echo -e "\e[31mBackup for '$tag' failed with status $backup_status\e[0m" fi } # Function to remove the backup remove_backup() { local tag="$1" read_settings echo "Removing backup for tag '$tag'..." # Rsync remove command rmfile="/home/$user/$backup_root/$tag" rm_cmd="ssh $user@$server rm -rf $rmfile" # Execute the removal command eval "$rm_cmd" rm_status=$? if [[ $rm_status -ne 0 ]]; then echo -e "\e[31mError: Failed to remove remote backup for tag '$tag'\e[0m" echo "Command failed: $rm_cmd" return 1 fi # Remove log entries while preserving header log_path="$HOME/.backuplog" if [[ -f "$log_path" ]]; then # Create a temporary file temp_file=$(mktemp) # Copy header (first line) if it exists if [[ -s "$log_path" ]]; then head -1 "$log_path" > "$temp_file" # Only copy non-matching lines after header tail -n +2 "$log_path" | grep -v "^\"$tag\"," >> "$temp_file" else # If log is empty, add header echo "\"tag\",\"timestamp\",\"command\",\"completion_time\"" > "$temp_file" fi # Replace the original with filtered content mv "$temp_file" "$log_path" echo -e "\e[32mBackup '$tag' removed successfully\e[0m" echo "Log entries for '$tag' have been removed from $log_path" else echo -e "\e[32mBackup '$tag' removed successfully\e[0m" echo "No log file found at $log_path" fi } # Function to list the backups with detailed timing information list_backups() { read_settings log_path="$HOME/.backuplog" echo "Backup Status Report ($(date '+%Y-%m-%d %H:%M:%S'))" echo "=========================================================" printf "%-8s %-15s %-10s %-20s %-15s\n" "TAG" "STATUS" "COUNT" "LAST BACKUP" "DAYS AGO" echo "--------------------------------------------------------" # Check if header exists in log file, if not, create it if [[ ! -f "$log_path" ]]; then echo "\"tag\",\"timestamp\",\"command\",\"completion_time\"" > "$log_path" echo "Created new log file with CSV headers." elif [[ $(head -1 "$log_path") != "\"tag\",\"timestamp\",\"command\",\"completion_time\"" ]]; then # Add header if it doesn't exist temp_file=$(mktemp) echo "\"tag\",\"timestamp\",\"command\",\"completion_time\"" > "$temp_file" cat "$log_path" >> "$temp_file" mv "$temp_file" "$log_path" echo "Added CSV headers to existing log file." fi # Loop through each tag in the taglist for tag in $taglist; do # Count occurrences of the tag in the log count=0 youngest="" days_ago="N/A" if [[ -f "$log_path" ]]; then # Skip header when counting count=$(grep -c "^\"$tag\"," "$log_path") # Get the newest backup date for this tag if [[ $count -gt 0 ]]; then # Extract dates and find the newest one dates=$(grep "^\"$tag\"," "$log_path" | cut -d',' -f2) youngest=$(echo "$dates" | sort -r | head -1) # Calculate days since last backup if [[ ! -z "$youngest" ]]; then youngest_seconds=$(date -d "$youngest" +%s) now_seconds=$(date +%s) days_diff=$(( (now_seconds - youngest_seconds) / 86400 )) days_ago="$days_diff days" fi fi fi # Determine status with colored output if [[ $count -eq 0 ]]; then status="Missing" status_color="\e[31m$status\e[0m" # Red elif [[ $count -gt 5 ]]; then status="Needs renewal" status_color="\e[33m$status\e[0m" # Yellow elif [[ ! -z "$youngest" ]]; then # Calculate days since last backup youngest_seconds=$(date -d "$youngest" +%s) now_seconds=$(date +%s) days_diff=$(( (now_seconds - youngest_seconds) / 86400 )) if [[ $days_diff -gt 7 ]]; then status="Needs to be run" status_color="\e[33m$status\e[0m" # Yellow else status="Up to date" status_color="\e[32m$status\e[0m" # Green fi else status="Missing" status_color="\e[31m$status\e[0m" # Red fi printf "%-8s %-15b %-10s %-20s %-15s\n" "$tag" "$status_color" "$count" "${youngest:-N/A}" "$days_ago" done echo "--------------------------------------------------------" echo "CSV log file: $log_path" echo "Run 'loci -l' to refresh this status report" } # Function to show backup stats show_stats() { read_settings log_path="$HOME/.backuplog" if [[ ! -f "$log_path" ]]; then echo "No backup log found at $log_path" return 1 fi echo "Backup Statistics" echo "=================" # Total number of backups total_backups=$(grep -v "^\"tag\"" "$log_path" | wc -l) echo "Total backups: $total_backups" # Backups per tag echo -e "\nBackups per tag:" for tag in $taglist; do count=$(grep "^\"$tag\"," "$log_path" | wc -l) echo " $tag: $count" done # Last backup time for each tag echo -e "\nLast backup time:" for tag in $taglist; do latest=$(grep "^\"$tag\"," "$log_path" | cut -d',' -f2 | sort -r | head -1) if [[ -z "$latest" ]]; then echo " $tag: Never" else # Calculate days ago latest_seconds=$(date -d "$latest" +%s) now_seconds=$(date +%s) days_diff=$(( (now_seconds - latest_seconds) / 86400 )) echo " $tag: $latest ($days_diff days ago)" fi done echo -e "\nBackup log file: $log_path" echo "To view in a spreadsheet: cp $log_path ~/backups.csv" } # Function to export log to CSV export_csv() { read_settings log_path="$HOME/.backuplog" export_path="${1:-$HOME/backup_export.csv}" if [[ ! -f "$log_path" ]]; then echo "No backup log found at $log_path" return 1 fi # Copy the log file to export location cp "$log_path" "$export_path" echo "Backup log exported to: $export_path" echo "You can now open this file in your spreadsheet application." } # Main function main() { if [[ "$1" == "-b" || "$1" == "--backup" ]] && [[ ! -z "$2" ]]; then backup "$2" elif [[ "$1" == "-r" || "$1" == "--remove" ]] && [[ ! -z "$2" ]]; then remove_backup "$2" elif [[ "$1" == "-l" || "$1" == "--list" ]]; then list_backups elif [[ "$1" == "-s" || "$1" == "--stats" ]]; then show_stats elif [[ "$1" == "-e" || "$1" == "--export" ]]; then export_csv "$2" elif [[ "$1" == "-h" || "$1" == "--help" ]]; then echo "Loci Backup Management Tool" echo "Usage:" echo " loci -b, --backup <tag> Create a backup with the specified tag" echo " loci -r, --remove <tag> Remove a backup with the specified tag" echo " loci -l, --list List all backup statuses" echo " loci -s, --stats Show backup statistics" echo " loci -e, --export [path] Export backup log to CSV (default: ~/backup_export.csv)" echo " loci -h, --help Show this help message" else echo "Usage: loci -b <tag> | loci -r <tag> | loci -l | loci -s | loci -e [path] | loci -h" fi }
- Comment on I wrote a python script to backup my home directory 1 week ago:
One needs to be compiled and the other is literally the de facto scripting language intended for exactly this purpose.
- Comment on I wrote a python script to backup my home directory 1 week ago:
A hilariously unnecessary Python script that could have easily been done in bash since it’s literally just a wrapper around rsync. 😅
When you’ve only got a Python-sized hammer in your toolbox, everything looks like a Python nail, I guess.
- Comment on What is best Lemmy App to use on iPhone? 4 weeks ago:
Voyager is the only open source one.
I would hope we would have learned enough from #enshittification by now that we would refuse to use others unless the devs open source their code.
- Comment on What Would a Fair and Community-Focused Monetization Model on the Fediverse Look Like? 1 month ago:
Sometimes things that are repeated over and over again are actually true.
Just because you don’t understand how the world works doesn’t make this untrue.
- Comment on What Would a Fair and Community-Focused Monetization Model on the Fediverse Look Like? 1 month ago:
I wrote that.
Done engaging with you. Thanks for the talk.
- Comment on What Would a Fair and Community-Focused Monetization Model on the Fediverse Look Like? 1 month ago:
I don’t have time to educate you but:
- civil asset forfeiture is a thing
- runaway inflation due to excessive money printing is a thing
- the work bank may not officially be a bank but what it is is a giant conglomerate of corporations that owns nations, takes part in coups, assasination, price fixing, and controls the dollar.
- Comment on [deleted] 1 month ago:
Get help, you fragile, easily-triggered white man.
- Comment on Retaking The Web Browser, One Small Step At A Time • AndreGarzia.com 1 month ago:
Bookmarklets: retaking the web browser one incredibly unsafe feature at a time.