Click an Ad

If you find this blog helpful, please support me by clicking an ad!

Monday, March 31, 2014

Automated Backup of a MySQL Database

I have a couple MySQL databases out here in the wilderness. I use Veeam Backup and Replication to back up my virtual machines, but Veeam doesn't have any way to quiet MySQL database activity down so that it can get a proper backup, that I'm aware of. So, I got my hands dirty and created the following process to automatically back up MySQL databases.


  • The first thing that needs to be done is that a user needs to be created within the MySQL instance that can be used for backups. I accomplish this on the server in MySQL Workbench. Under Server Administration, click on Security. Add a user account, give it a nice password, and add it to the BackupAdmin role.
  • The MySQL server is not a domain-joined computer, so I created a local Windows account (MySQLWinBackup), and assigned the account the "Log on as batch" right.
  • I created a local folder named C:\DB_Backup. This folder should be shared to "Everyone", and then the NTFS permissions modified so that the local Windows backup account has full permissions.
  • The following Powershell script file needs to be created. I store my scripts in C:\PS:

#--------------------- BEGIN SCRIPT -------------------------------

#Name of Server
$ServerName = "WebServer"

#The Path to the mysqldump.exe program. This is the program that backs up the MySQL database natively.
$PathToMySQLDump = "C:\MySQL\bin\mysqldump.exe"

#Credentials of the MySQL user account
$Username = "MySQLBackupAccount"
$Password = "MySQLBackupAccountPassword"

#Get today's date, to be used for naming purposes
$Date = (get-date).ToString('MM-dd-yyyy')

#Where to store the backup files
$LocalBackupPath = "C:\DB_Backup"

#Backup all of the Databases
cmd /c " `"$PathToMySQLDump`" --routines --events --user=$UserName --password=$Password --all-databases > $LocalBackupPath\$ServerName-AllDataBasesBackup-$Date.sql "

#--------------------- END SCRIPT -------------------------------

  • Now, I set that Powershell script to execute daily at 5:10PM in Task Scheduler.
  • I run the scheduled task and find out how long it's going to take. This information will be used later on.
  • Over on my backup server, I create another script. This script handles moving the backup files created earlier off-SAN and off-site:
#--------------------- BEGIN SCRIPT -------------------------------

#Name of Server
$ServerName = "WebServer"

#Path to the location where the MySQL server put the backups
$RemoteBackupPath = "C:\DB_Backup"

#Off-SAN copy location
$OffSANCopyLocation = "\\OnSiteNASDevice\MySQLBackup"

#Off-Site copy location
$OffSiteCopyLocation = "\\DR_NAS_Device\MySQLBackup"

#Body of the notification email
$Body = "."

#Map Y drive to the MySQL server's backup location:
net use Y: \\WebServer\DB_Backup /user:"MySQLWinBackup" MySQLWinBackupPassword

#Get a file count for success/failure test
$FileTest = (get-childitem Y:\ | measure).count

#Success/Failure Test - If the file count does not come back as expected, send an email, THEN EXIT THE SCRIPT
If ($FileTest -ne 1){
$Body = "The correct number of files is not present on the MySQL Server to be distributed off-site and off-SAN."
Send-Mailmessage -from "helpdesk@contoso.com" -to "itreporting@contoso.com" -subject "PS Report - MySQL Backup Status - FAILURE - WEBSERVER" -smtpserver contosomailserver -body $body
exit
}

#Copy the files from the MySQL Server to the off-site and off-SAN locations
copy-item -Path "Y:\*.*" -Destination "$OffSiteCopyLocation"
copy-item -Path "Y:\*.*" -Destination "$OffSANCopyLocation"

#Delete the backup files stored locally on the MySQL server
remove-item "Y:\*.*"

#For off-site location, get the creationtime and delete anything older than 7 days
$Files = (Get-childitem $OffSiteCopyLocation)
Foreach ($file in $files){
$FileAge = ((get-date) - ($file.creationtime)).totaldays
If ($FileAge -gt 7){
remove-item $File.FullName -Force
} #End If
} #End Foreach

#For off-SAN location, get the creationtime and delete anything older than 7 days
$Files = (Get-childitem $OffSANCopyLocation)
Foreach ($file in $files){
$FileAge = ((get-date) - ($file.creationtime)).totaldays
If ($FileAge -gt 7){
remove-item $File.FullName -Force
} #End If
} #End Foreach

#Send a success notification email
Send-Mailmessage -from "helpdesk@contoso.com" -to "itreporting@contoso.com" -subject "PS Report - MySQL Backup Status - SUCCESS - WEBSERVER" -smtpserver contosomailserver -body $body

#Unmap the MySQL Backup drive
net use Y: /delete

#--------------------- END SCRIPT -------------------------------

  • I save this script in the C:\PS folder on my backup server, then set a scheduled task to run the script at an appropriate time. How I determine what's appropriate? I look at the run time of the backup on the server itself, and then pick what's comfortable to me. In my case, the backup takes about 2 minutes to run, so I set this task to execute 10 minutes after the start of the MySQL backup script.

The resulting workflow is:
  1. MySQL Server backs up databases to its C drive.
  2. Backup server checks for the existence of the new backup file. If not ok, send failure email alert.
  3. Backup server copies that file to 2 other locations, then deleted the originals on the MySQL Server.
  4. Backup server deletes backup files older than 7 days at the 2 other locations.
  5. Backup Server sends success email alert.

Friday, March 28, 2014

Some PC App Recommendations

This past week I had to bite the bullet and reformat my work laptop. Piriform's CCleaner was a big help, as I was able to export a list of all installed apps. To do so, open up CCleaner and click on "Tools". At this point "Uninstall" should be highlighted, and on the bottom right-hand side, click on "Save to text file...".

Once I had my list, I installed all of the apps on my new laptop. I figured that I would note some helpful items here. I use Windows 7, so if you're running Windows 8, then your experience could be different.


  • Actual Multiple Monitors allows me to have the Windows 7 taskbar extend to my second screen. I can pin separate applications to this taskbar.
  • Advanced IP Scanner is my go-to address space scanner.
  • Autohotkey is something I would like to play with more, but my killer app for this so far is this gem, which allows me to use Ctrl+V to paste into the command prompt and Powershell.
  • Beyond Compare allows me to compare files, folders, and even registry entries. I've been using this for many years.
  • EMCO makes two utilities that I really like: MAC Address Scanner and Remote Console. Usually I use Powershell remoting, but this has come in handy when there is a configuration issue on the client side and I'm not able to use remote Powershell.
  • Image Resizer Powertoy Clone for Windows allows me to right click on picture files and quickly resize them.
  • NetSetMan allows me to quickly switch between different network adapter configurations, such as when I need a static IP address at a remote site, or when I want a static address on the iSCSI network.
  • QtTabBar gives me the ability to have tabs in Windows Explorer. This is a killer app......
  • Multiplicity allows me to have a kind of software KVM. If you've seen my setup, I have two screens above and two below. Each set of two is a different computer, and this lets me control all four screens with on keyboard and mouse.
  • Tabs for Excel was a big win with the accounting department when I discovered it and installed it for them. Now I can have multiple spreadsheets open in one Excel window.
  • VirtualCloneDrive runs in my system tray and allows me to mount ISO files.
  • Vistaswitcher (don't be scared off by "Vista" in the name), gives you a much better interface when using Alt-Tab to switch between open applications. Instead of just showing the name of the running apps, it shows you what's within the window.
  • Windows Grep will let me search through a bunch of text files for certain strings. I know I can do this through Powershell, and this is a total crutch, but sometimes things are just easier with a GUI.
  • WizMouse allows me to use my mouse's scroll wheel to scroll through something without changing my active window. All I have to do is put my mouse over the inactive app's window and scroll, and it works!




Monday, March 24, 2014

Pulling out lines that contain X from a text file

This is going to be a short one, and really is more for my reference, but hopefully it helps other people.

I had a long log file, about 490MB, and I was looking for entries that had certain content. Specifically, I wanted any line that had "5156" in it.

Get-Content c:\temp\LogFile.txt | where-object {$_ -match '5156'} | set-content c:\temp\output.txt

After the line above executes, only lines that contain 5156 are copied to the output file.

I'm going to be using this a lot in the future, I think.....

Friday, March 21, 2014

Use This Powershell Script to List Which VMs are Running on each VMware Host in Your Cluster

I don't use this that often, but sometimes I just want to know which VMs are running on each of my VMware ESXi hosts. I find it easier to fire off the script than to open up vCenter if I want to know which host a VM is running on, and what other VMs are running on that host.

#-------------------------------- BEGIN SCRIPT --------------------------------

#Get Credentials
$credential = get-credential stemalyc@kalamazoocity.org

#Add the VMware Snapin
add-pssnapin Vmware.VimAutomation.Core

#Connect to the vCenter Server
connect-viserver -server cityvc.kalamazoocity.org -credential $credential

#Get all the hosts
$VMHosts = (Get-VMHost | select Name | sort name)

#Get all the VMs
$VMs = (Get-VM | select name, vmhost)

#Find the number of hosts, which will be our counter maximum later on
$HostQty = (($VMhosts | measure).count)

#Initialize the counter to zero
$i = 0

#While the counter is less than or equal to the host counter
While ($i -le $HostQty){
#List the VMs on the host. I use $i here to reference the exact host in the $VMHosts array.
$Listing = ($VMs | where {$_.vmhost -like ($VMHosts[$i].name)} | sort name)
#Output the list to the screen with Format-Table (ft)
$Listing | ft
#Blank out the list variable so it can be reused
$Listing = $null
#Increment the counter
$i++
} #End While

#Create a pause at the end of the script
$Pause = Read-Host "Press Enter to Continue"

#-------------------------------- END SCRIPT --------------------------------