Saturday, March 3, 2012

PowerShell scripting for automation and documentation

In a previous post I shared a PowerShell script that automated finding folder sizes.  That script was meant to be reused as-is by having parameters passed to it when it is called from a PowerShell window.  The script that I'm posting today is different.  This one is meant to not only automate a process but document what I did at a particular time.  I cover two rules of systems administration in one script "automate everything" and "document everything".  I save a copy of these one-time scripts to use as a template when I need to perform the same operation under different conditions.  They also serve as a record of how I did something in a particular instance because I save them as part of my change management documentation.  Here's a sanitized version of the script that I have saved as my template.

# PowerShell Script
# Name:    robocopyFilesToArchive.ps1
# Purpose: use robocopy to move files from one drive to another
#          and keep a log of the move
# Author:  Matthew Sanaker,
# Date:    3/2/2012
# USAGE:   this is a one-time script written to automate and document this process
#          to reuse it save it with a new name and change variables as necessary

$date = Get-Date;
$year = $date.Year;
$month = "{0:D2}" -f $date.Month;
$day = "{0:D2}" -f $date.Day;
$timestamp = $year.ToString() + $month.ToString() + $day.ToString();

$source = "D:\Data";
$destination = "E:\Archives\Data";
$logFolder = "E:\robocopyLogs";
$logFile = $logFolder + "\" + "robocopyData_$timestamp.log";

if (!(Test-Path $logFolder))
New-Item $logFolder -type directory;

if (!(Test-Path $destination))
New-Item $destination -type directory;

robocopy $source $destination /E /ZB /COPY:DATOU /MOVE /R:2 /W:1 /LOG+:$logFile /NP /TEE;

What the script does:

The first block of code retrieves the current date from the system, takes it apart and reassembles it into a time stamp string variable that resembles a conventional BIND DNS serial number.  I like to use these serial numbers at the end of configuration files, log files and other documents to keep them simultaneously sorted by name and date when displayed in the filesystem.  First I use Get-Date to build my $date object.  I then get the year, month and day by turning those properties from my $date object into new objects.  I use .Net number formatting when creating the month and day objects so that I always have two digit months and days.  ' "{0:D2}" -f ' tells PowerShell take object 0 and display it with 2 digits of precision adding leading zeros if necessary. (follow footnote 1 for more options and information)

In the next block I create the variables that I pass to robocopy to move my data.  Those are self-explanatory.  The next two blocks test the paths for both my log file and the destination of my data and create them if they don't exist.  Since robocopy won't create folders for either the destination that you specify or the folder you want your log to be written to, you have to make sure that they exist before you run robocopy otherwise robocopy with throw an error and exit.  In PowerShell, the "!" acts to negate a statement.  Test-Path returns a boolean, so if a file path exists, it returns true otherwise it returns false.  So the statement "if (!(Test-Path $destination))" says "if the folder $destination doesn't exist".  If the if statement evaluates the condition in parenthesis and it is true, PowerShell executes the code between the curly braces.  If the condition in parenthesis is false PowerShell skips the code in the curly braces and moves on.  The statement in the curly braces in each block creates the folder in question.

Once everything is set, robocopy is executed.  Robocopy has a lot of options, I will explain the ones that I have chosen.  $source and $destination are obvious.  "/E" says include empty subfolders.  "/ZB" help recover from errors where a copy gets interrupted or access is denied.  /COPY:DATOU says copy the data, file attributes, timestamp, owner and audit information.  I chose not to copy permissions because I was moving this data to a read-only archive.  /MOVE says copy both files and folders and delete them from the source when finished.  /R and /W are retry options, I specified retry twice and wait 1 second between retries.  Since I wanted to log robocopy's success or failure, I choose /LOG+ to append output to my specified log file, /NP (no progress) so that the file is actually readable and /TEE so that I can also see the output in the shell while it's happening.

Of course robocopy could have been called from a single line right in PowerShell or a cmd window.  The log file alone could serve as good documentation and I always open them up and search for the word "error", but having both files makes the documentation more complete.


No comments:

Post a Comment