|
require "ftools"
|
|
|
|
# UNRESOLVED PROBLEMS
|
|
# Backup logs: move complains of readlink unimplemented in ftools. Used to work yesterday.
|
|
# Apparently this was from multiple file writers locking file.
|
|
# Make trimbackup and backup into one file with small front end. Front end simply takes
|
|
# robocopy flags, base log name, and batch file name.
|
|
# For some reason this script (and trimbackup.rb) unexpectedly quit after
|
|
# backing up a machine after a few days. No idea why. It is in the
|
|
# backupmachine loop in main. I'm trying to see if .bat crashes system()
|
|
# or if its something else weird that crashes ruby. I'm not having much
|
|
# luck debugging this.
|
|
|
|
# CONSTANTS
|
|
|
|
NumLogs = 8
|
|
|
|
BackupList = "directoryList.txt"
|
|
|
|
BaseLogName = "backup"
|
|
|
|
Log = "#{BaseLogName}01.log"
|
|
|
|
OneDayInSeconds = 24*60*60
|
|
|
|
# constants used for array of start and end times for runhours string and window Start/End
|
|
|
|
WorkStart = [8,00] # 8 am
|
|
WorkEnd = [17,30] # 5:30 pm
|
|
|
|
# time window constants
|
|
|
|
Before = 0
|
|
In = 1
|
|
AfterSameDay = 2
|
|
AfterLaterDay = 3
|
|
|
|
def formatToTwoInts(value)
|
|
str = ""
|
|
if value < 10
|
|
str += "0#{value}"
|
|
else
|
|
str += "#{value}"
|
|
end
|
|
end
|
|
|
|
tmp = ""
|
|
tmp += formatToTwoInts(WorkEnd[0])
|
|
tmp += formatToTwoInts(WorkEnd[1])
|
|
tmp += "-"
|
|
tmp += formatToTwoInts(WorkStart[0])
|
|
tmp += formatToTwoInts(WorkStart[1])
|
|
|
|
RunHours = tmp
|
|
|
|
# RoboCopy flags
|
|
#
|
|
# /xjd - exclude junction points: avoid infinite path name for vista
|
|
# /a-:rash - turn off specified attributes in copied files
|
|
# /np - turn off % progress indicator
|
|
# /r:0 - retry failed copies 0 times
|
|
# /fft - Fat File Times: useful for third party NTFS support
|
|
# /rh:1800-0730 - only copy files between 6:00 pm and 7:30 am
|
|
# /pf - check time per file
|
|
# /s - include all subdirs too (but not empty ones)
|
|
# /tee - output to screen while outputting to log file
|
|
# /log+:fname - append output to logfile named fname
|
|
# /xd "Temporary Internet Files" - exclude all temp internet files directories
|
|
|
|
RoboCopyFlags = "/xjd /a-:rash /np /r:0 /fft /rh:#{RunHours} /pf /s /tee /log+:#{Log} /xd \"Temporary Internet Files\" \"System Volume Information\" \"Program Files\" Cache Recycler"
|
|
|
|
# GLOBALS
|
|
|
|
# used to hold machines etc. to backup
|
|
@usrs = []
|
|
@psswrds = []
|
|
@machines = []
|
|
@srcShares = []
|
|
@srcDirs = []
|
|
@destMachines = []
|
|
@destShares = []
|
|
|
|
# FUNCTIONS
|
|
|
|
def appendLog(str)
|
|
File.open(Log,"a") do | file |
|
|
file.print(str,"\n")
|
|
end
|
|
end
|
|
|
|
def saveLogs()
|
|
NumLogs.downto(1) do | logNum |
|
|
case logNum
|
|
when 1,2,3,4,5,6,7,8
|
|
logFile = "#{BaseLogName}0#{logNum}.log"
|
|
savedFile = "#{BaseLogName}0#{logNum+1}.log"
|
|
when 9
|
|
logFile = "#{BaseLogName}0#{logNum}.log"
|
|
savedFile = "#{BaseLogName}#{logNum+1}.log"
|
|
else
|
|
logFile = "#{BaseLogName}#{logNum}.log"
|
|
savedFile = "#{BaseLogName}#{logNum+1}.log"
|
|
end
|
|
if FileTest.exist?(logFile)
|
|
File.rm_f(savedFile) if FileTest.exist?(savedFile)
|
|
# file move from curr log to next log
|
|
File.move(logFile,savedFile)
|
|
end
|
|
end
|
|
logFile = "#{BaseLogName}01.log"
|
|
File.rm_f(logFile) if FileTest.exist?(logFile)
|
|
end
|
|
|
|
def readBackupList()
|
|
@usrs = []
|
|
@psswrds = []
|
|
@srcMachines = []
|
|
@srcShares = []
|
|
@srcDirs = []
|
|
@destMachines = []
|
|
@destShares = []
|
|
file = File.new(BackupList).each do | fileSpec |
|
|
next if (fileSpec.length > 0) and (fileSpec[0].chr == "#")
|
|
if fileSpec =~ /(.*),(.*),(.*),(.*),(.*),(.*),(.*)/
|
|
#print "Found one: #{$1} #{$2} #{$3} #{$4} #{$5} #{$6} #{$7}\n"
|
|
@usrs << $1
|
|
@psswrds << $2
|
|
@srcMachines << $3
|
|
@srcShares << $4
|
|
@srcDirs << $5
|
|
@destMachines << $6
|
|
@destShares << $7
|
|
end
|
|
end
|
|
end
|
|
|
|
def decrypt(pss)
|
|
outStr = ""
|
|
pss.each_byte do | ch |
|
|
if (ch > 79) # 80 <= ch <= 126
|
|
newCh = (ch - 47).chr
|
|
#print "[#{ch.chr}] went to [#{newCh}]\n"
|
|
outStr << newCh
|
|
else # 33 <= ch <= 79
|
|
newCh = (ch + 47).chr
|
|
#print "[#{ch.chr}] went to [#{newCh}]\n"
|
|
outStr << newCh
|
|
end
|
|
end
|
|
outStr
|
|
end
|
|
|
|
def backupMachine(usr,psswrd,machine,share,directory,destMachine,destShare)
|
|
|
|
# build batch file
|
|
|
|
# File.open("copyIt.bat","w") do | file |
|
|
# file.print("net use q: /delete\n")
|
|
# file.print("net use q: \"\\\\#{machine}\\#{share}\" #{decrypt(psswrd)} /user:#{usr}\n")
|
|
# file.print("robocopy \"q:\\#{directory}\" \"\\\\#{destMachine}\\#{destShare}\\#{machine}\\#{share}\\#{directory}\" #{RoboCopyFlags}\n")
|
|
# file.print("net use q: /delete\n")
|
|
# end
|
|
|
|
appendLog("\nStart backup of \\\\#{machine}\\#{share}\\#{directory} ********")
|
|
|
|
srcShare = "\"\\\\#{machine}\\#{share}\""
|
|
srcDir = "\"q:\\#{directory}\""
|
|
dstDir = "\"\\\\#{destMachine}\\#{destShare}\\#{machine}\\#{share}\\#{directory}\""
|
|
|
|
# run batch file
|
|
|
|
system("doBackupRobo.bat #{usr} #{decrypt(psswrd)} #{srcShare} #{srcDir} #{dstDir} #{RoboCopyFlags}")
|
|
|
|
appendLog("End backup of \\\\#{machine}\\#{share}\\#{directory} **********\n")
|
|
end
|
|
|
|
def forbiddenTime(currTime, startForbiddenWindow, endForbiddenWindow)
|
|
forbidden = nil
|
|
if ((startForbiddenWindow <= currTime) and (currTime <= endForbiddenWindow))
|
|
forbidden = true
|
|
else
|
|
forbidden = false
|
|
end
|
|
forbidden
|
|
end
|
|
|
|
def sleepUntilOpenWindow(currTime,endForbiddenWindow)
|
|
secondsToSleep = endForbiddenWindow - currTime
|
|
if secondsToSleep > 0.0
|
|
print "Sleeping #{secondsToSleep} seconds until next backup window at #{endForbiddenWindow}\n"
|
|
sleep(secondsToSleep)
|
|
else # looks impossible to get here as this method is used
|
|
print "Weird timing error in sleepUntilOpenWindow\n"
|
|
print " Called with currTime beyond #{endForbiddenWindow}: #{currTime}!\n"
|
|
end
|
|
end
|
|
|
|
def classifyPeriod(time,startWin,endWin)
|
|
value = Before - 1
|
|
if time < startWin
|
|
value = Before
|
|
elsif (startWin <= time) and (time <= endWin)
|
|
value = In
|
|
else
|
|
if ((time.year == endWin.year) and
|
|
(time.month == endWin.month) and
|
|
(time.day == endWin.day))
|
|
value = AfterSameDay
|
|
else
|
|
value = AfterLaterDay
|
|
end
|
|
end
|
|
value
|
|
end
|
|
|
|
def nextDayWindowEnd(fromTime)
|
|
endWindow =
|
|
Time.local(fromTime.year, fromTime.month, fromTime.day,
|
|
WorkEnd[0], WorkEnd[1], 0, 0) + OneDayInSeconds
|
|
endWindow
|
|
end
|
|
|
|
# MAIN PROGRAM
|
|
|
|
until (true == false) do
|
|
|
|
print "Starting a pass through the backup loop\n"
|
|
|
|
iterStart = Time.now
|
|
|
|
startForbiddenWindow =
|
|
Time.local(iterStart.year, iterStart.month, iterStart.day,
|
|
WorkStart[0], WorkStart[1], 0, 0)
|
|
endForbiddenWindow =
|
|
Time.local(iterStart.year, iterStart.month, iterStart.day,
|
|
WorkEnd[0], WorkEnd[1], 0, 0)
|
|
|
|
started = classifyPeriod(iterStart,startForbiddenWindow,endForbiddenWindow)
|
|
|
|
# run the file copying
|
|
saveLogs
|
|
readBackupList
|
|
0.upto((@srcMachines.length)-1) do | i |
|
|
backupMachine(@usrs[i],@psswrds[i],
|
|
@srcMachines[i],@srcShares[i],@srcDirs[i],
|
|
@destMachines[i],@destShares[i])
|
|
end
|
|
|
|
iterEnd = Time.now
|
|
|
|
ended = classifyPeriod(iterEnd,startForbiddenWindow,endForbiddenWindow)
|
|
|
|
# determine how long to sleep based on when started and ended
|
|
|
|
if (started == Before) and (ended == Before)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
elsif (started == Before) and (ended == In)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
elsif (started == Before) and (ended == AfterSameDay)
|
|
endForbiddenWindow = nextDayWindowEnd(iterEnd)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
elsif (started == Before) and (ended == AfterLaterDay)
|
|
# do nothing: next iteration and backup immediately
|
|
elsif (started == In) and (ended == AfterSameDay)
|
|
endForbiddenWindow = nextDayWindowEnd(iterEnd)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
elsif (started == In) and (ended == AfterLaterDay)
|
|
# do nothing: next iteration and backup immediately
|
|
elsif (started == AfterSameDay) and (ended == AfterSameDay)
|
|
endForbiddenWindow = nextDayWindowEnd(iterEnd)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
elsif (started == AfterSameDay) and (ended == AfterLaterDay)
|
|
endForbiddenWindow = nextDayWindowEnd(iterStart)
|
|
if (iterEnd < endForbiddenWindow)
|
|
sleepUntilOpenWindow(iterEnd,endForbiddenWindow)
|
|
else
|
|
# do nothing: next iteration and backup immediately
|
|
end
|
|
else
|
|
print "Unhandled combo of start #{started} and end #{ended}\n"
|
|
end
|
|
|
|
end
|