Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Help about MediaWiki
FUTO
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Introduction to a Self Managed Life: a 13 hour & 28 minute presentation by FUTO software
(section)
Main Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==== 7.1 Backup script creation: ==== This script below will allow you to have your virtual machines backed up automatically. It does the following: * Shuts down the virtual machine * Copies its disk image qcow2 file to the <code>/mediapool/vmbackups</code> zfs dataset * Copies its configuration so it can be set up again * Keeps five backups but deletes the oldest ones after you have five. This means the following: * You can mess things up by deleting files you weren’t supposed to, mess up configurations and programs, and restore everything to where it was last week with one or two kindergarten level GNU/Linux commands. * You can migrate this to another computer entirely & start the virtual machine up there. shuts each virtual machine down one by one, backs up the virtual Save this as <code>/root/vm_backup.sh</code>: <pre># Open the text editor sudo nano -w /root/vm_backup.sh</pre> <pre>#!/bin/bash # thank you to stack overflow for giving me the courage to wade through 100s of posts and hack together something that looks like it works. # config for backups BACKUP_DIR="/mediapool/vmbackups" LOG_FILE="/var/log/vm_backups.log" RETENTION_DAYS=56 # how long to keep backups # Function to write messages to our log file` log_message() { # Get the current timestamp and message echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" } # Function to find the actual disk path for a VM when the default path doesn't exist # Uses virsh dumpxml to get the disk source path from the VM's XML configuration find_vm_disk_path() { local vm_name=$1 # Get the VM's XML configuration and extract the first disk source path # Using grep with -o to only output the matched portion # Using sed to extract just the path part from the source attribute local disk_path=$(virsh dumpxml "$vm_name" | grep -o "source file='[^']*'" | head -n1 | sed "s/source file='\(.*\)'/\1/") # Check if we found a path and if it exists if [ -n "$disk_path" ] && [ -f "$disk_path" ]; then echo "$disk_path" return 0 else return 1 fi } # main backup function backup_vm() { local virtual_machine_name=$1 # The name of the virtual machine we're backing up local date_stamp=$(date +%Y%m%d) # Today's date for the backup file name local source_file="/var/lib/libvirt/images/${virtual_machine_name}.qcow2" # Where the virtual machine is # If the default path doesn't exist, try to find the actual disk path if [ ! -f "$source_file" ]; then log_message "Default disk path not found for ${virtual_machine_name}, searching XML configuration..." local found_path=$(find_vm_disk_path "$virtual_machine_name") # If we found a valid path, use it instead if [ -n "$found_path" ]; then log_message "Found alternate disk path: ${found_path}" source_file="$found_path" fi fi local backup_file="${BACKUP_DIR}/${virtual_machine_name}-${date_stamp}.qcow2" # Where we're putting the backup of it local config_file="${BACKUP_DIR}/${virtual_machine_name}-${date_stamp}.xml" # Where it saves the virtual machine config # Check if source file exists before attempting backup if [ ! -f "$source_file" ]; then log_message "ERROR: Source file $source_file does not exist for ${virtual_machine_name}" return 1 fi # Announce backup is starting log_message "Starting backup process for ${virtual_machine_name}" # Save virtual machine's config virsh dumpxml "$virtual_machine_name" > "$config_file" # Set ownership and permissions for config file chown libvirt-qemu:kvm "$config_file" chmod 644 "$config_file" # Try to shut down the virtual machine nicely log_message "Shutting down ${virtual_machine_name}" virsh shutdown "$virtual_machine_name" # Wait patiently for the virtual machine to shut down local count=0 while [ "$(virsh domstate $virtual_machine_name)" != "shut off" ] && [ $count -lt 30 ]; do sleep 10 count=$((count + 1)) done # If it doesn't turn off, make it turn off(like holding the power button) if [ "$(virsh domstate $virtual_machine_name)" != "shut off" ]; then log_message "WARNING: Force shutting down ${virtual_machine_name}" virsh destroy "$virtual_machine_name" sleep 10 fi # Make sure it's actually off - trust but verify if [ "$(virsh domstate $virtual_machine_name)" != "shut off" ]; then log_message "ERROR: Failed to shut down ${virtual_machine_name}" return 1 fi # Create the backup - doesn't use compression since qemu-img convert compression is single threaded and insanely slow log_message "Creating backup of ${virtual_machine_name}" if ! qemu-img convert -p -f qcow2 -O qcow2 "$source_file" "$backup_file"; then log_message "ERROR: Backup failed for ${virtual_machine_name}" virsh start "$virtual_machine_name" return 1 fi # Set ownership and permissions for backup file chown libvirt-qemu:kvm "$backup_file" chmod 644 "$backup_file" # Make sure the backup isn't insanely small since that means this didn't work # Fixed stat command for Linux systems local source_size=$(stat -c%s "$source_file") local backup_size=$(stat -c%s "$backup_file") if [ "$backup_size" -lt 1048576 ]; then # Less than 1MB is suspicious - like a $5 "genuine" Rolex log_message "ERROR: Backup file suspiciously small for ${virtual_machine_name}" rm -f "$backup_file" "$config_file" virsh start "$virtual_machine_name" return 1 fi # Turn virtual machine back on when backup is done. log_message "Starting ${virtual_machine_name}" virsh start "$virtual_machine_name" # Wait for it to come back online count=0 while [ "$(virsh domstate $virtual_machine_name)" != "running" ] && [ $count -lt 12 ]; do sleep 5 count=$((count + 1)) done # Make sure it actually started(inspect what you expect) if [ "$(virsh domstate $virtual_machine_name)" != "running" ]; then log_message "ERROR: Failed to start ${virtual_machine_name}" return 1 fi # announce that it worked log_message "Backup of ${virtual_machine_name} completed!" # Clean up old backups - because nobody likes a full hard drive log_message "Cleaning up old backups for ${virtual_machine_name}" find "$BACKUP_DIR" -name "${virtual_machine_name}-*.qcow2" -mtime +${RETENTION_DAYS} -exec rm -f {} \; # Delete old qcow2 files find "$BACKUP_DIR" -name "${virtual_machine_name}-*.xml" -mtime +${RETENTION_DAYS} -exec rm -f {} \; # Delete old xml files } # Start of the main backup process log_message "Starting backup process" # Make sure we're running as root if [ "$EUID" -ne 0 ]; then log_message "ERROR: Must run as root" exit 1 fi # Check if the backup directory exists if [ ! -d "$BACKUP_DIR" ]; then log_message "ERROR: Backup directory $BACKUP_DIR does not exist" exit 1 fi # Get list of ALL virtual machines, not just running ones # Changed to list all VMs instead of just running ones VMS=($(virsh list --all --name)) # Check if we have enough disk space to back up available_space=$(df -B1 "$BACKUP_DIR" | awk 'NR==2 {print $4}') required_space=0 # Calculate how much space we need for virtual_machine in "${VMS[@]}"; do if [ -n "$virtual_machine" ]; then # Try the default path first local_path="/var/lib/libvirt/images/${virtual_machine}.qcow2" # If default path doesn't exist, try to find actual path if [ ! -f "$local_path" ]; then local_path=$(find_vm_disk_path "$virtual_machine") || continue fi if [ -f "$local_path" ]; then virtual_machine_size=$(du -b "$local_path" 2>/dev/null | cut -f1) required_space=$((required_space + virtual_machine_size)) fi fi done # Make sure we have enough space if [ "$available_space" -lt "$required_space" ]; then log_message "ERROR: Insufficient space in backup directory" exit 1 fi # loop for backing up every virtual machine for virtual_machine in "${VMS[@]}"; do if [ -n "$virtual_machine" ]; then backup_vm "$virtual_machine" fi done # announce it's all done log_message "Backup process completed!" </pre> <blockquote>'''Nerd note: This script would be laughed out of the room for use in production environments for major web companies & datacenters.''' This script turns off the virtual machine to back it up. This means that at 1 AM, the service goes down. This would be unacceptable in a production environment where people expect the service to be available 24/7. There are ways to do live backups where you flush mysql tables and lock them, make redis background save, pause call processing in asterisk, pause io, create atomic snapshots, coordinate with databases of all the different programs…. the audience of this guide is a person running a home server in his closet. Do you really want to subject a beginner to docker volumes that may not be in a consistent state, email delivery/receipt being interrupted, database transactionst hat are messed with in the middle fo a write, corrupt call recordings, partially written large files, all so someone can get live backups of a server in their closet, you monster? If you need that level of uptime, you’re not a newbie reading this guide. or you are, and you need to hire a consultant to set you up with something like veeam. To subject a newbie to the risk of error/corruption/screwups that comes with doing live backups for these things when they’re at the level of this guide being helpful to them is cruel. </blockquote> <span id="set-permissions-so-script-works"></span>
Summary:
Please note that all contributions to FUTO may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
FUTO:Copyrights
for details).
Do not submit copyrighted work without permission!
To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:
Cancel
Editing help
(opens in new window)