How I implemented Shadowspawn with Robocopy

870 views
Skip to first unread message

Nathaniel

unread,
Oct 7, 2011, 9:41:47 AM10/7/11
to ShadowSpawn Support
I figured since I wrote this for work for my 50 or so mobile Windows 7
users and it's been working well I've release it for everyone. Time
permitting I'll redo this in powershell. Probably be a one liner
script :)

Abstract:
Using Windows 7 scheduling, I run an hourly run of Robocopy that
mirriors the C:\Users\<logged in user>\ snapshot from Shadowspawn to a
network share if it detects its in the corporate office. It writes out
events to the Application Event log for record keeping. Installation
path is C:\Program Files\Robocopy. A built MSI installs the following
files:
08/23/2011 03:52 PM 728 driveletter.cmd
07/28/2011 12:55 PM 780 installschedule.cmd
08/23/2011 02:51 PM 89 netusetest.cmd
07/28/2011 12:12 PM 239 rm_schedule.cmd
04/18/2003 06:06 PM 79,872 robocopy.exe
09/16/2011 04:27 PM 3,698 script.cmd
08/05/2011 10:46 AM 71,680 ShadowSpawn.exe
08/05/2011 10:46 AM 1,887,232 ShadowSpawn.pdb
04/18/2011 09:56 AM 125 Uninstall_schedule.cmd
04/15/2011 01:30 PM 158,872 XCACLS.vbs

into C:\Program Files\Robocopy then executes installschedule.cmd:

REM @echo off
REM
REM Installer for the script to backup the user profile
REM
SchTasks /Create /SC HOURLY /mo 1 /RU DOMAIN\wrkstnbkpuser /RP
"PASSWORD" /RL HIGHEST /TN "Current User profile backup" /TR "c:
\Progra~1\Robocopy\script.cmd" > NUL
FOR /F "usebackq tokens=2" %%G IN (`"C:\Windows\System32\qwinsta" ^|
findstr console`) DO set curuser=%%G

REM Get unused drive letters and select one at random
setlocal
setlocal enabledelayedexpansion
set "_DRIVE.LETTERS.FREE=Z Y X W V U T S R Q P O N M L K J I H G "
for /f "tokens=1,2 delims=: " %%a in ('netusetest.cmd') do (
set "_DRIVE.LETTERS.USED=!_DRIVE.LETTERS.USED!%%a"
set "_DRIVE.LETTERS.FREE=!_DRIVE.LETTERS.FREE:%%a =!"
)
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:~0,26%
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:,@=, @%
REM set _DRIVE.LETTERS

REM Get the string's length
set #=%_DRIVE.LETTERS.FREE%
set length=0
:loop
if defined # (
set #=%#:~1%
set /A length += 1
goto loop
)
set /A length="!length!/2"
set /A RANDVAR="%RANDOM%%%%length%"
for /f "tokens=%RANDVAR%" %%c in ("%_DRIVE.LETTERS.FREE%") do set
_source=%%c:


net use %_source% "\\REMOTESERVER\SHARE$" > NUL
if %errorlevel% NEQ 0 goto :eof
if not exist "%_source%\%curuser%\" mkdir "q:\%curuser%" > NUL
cscript.exe XCACLS.vbs %_source%\%curuser%\ /E /G DOMAIN\%curuser%:F /
I enable > NUL
if not exist "%_source%\%curuser%\%COMPUTERNAME%\" mkdir "%_source%\
%curuser%\%COMPUTERNAME%" > NUL
cscript.exe XCACLS.vbs %_source%\%curuser%\ /E /G DOMAIN\%curuser%:F /
I enable > NUL
net use %_source% /delete /yes > NUL
EOF

Which installs the hourly backup script. The DOMAIN\wrkstnbkpuser is a
local backup administrator (not administrator!). The script also
creates the folder path and security so only that user can view those
files. Lastly it runs rm_schedule.cmd which erases installschedule.cmd
so the password is not known for the backup account:
@echo off
REM
REM Remove Installer for the script to backup the user profile
REM
cd "C:\Program Files\Robocopy"
if exist "C:\Program Files\Robocopy\installschedule.cmd" del /F /Q "C:
\Program Files\Robocopy\installschedule.cmd" > NUL
EOF

When the hour occurs the script.cmd is run:
@echo off
REM
REM Backup Script for backing up current user
REM

REM Set current logged in user as null
set curuser=
FOR /F "usebackq tokens=2" %%G IN (`"C:\Windows\System32\qwinsta" ^|
findstr console`) DO set curuser=%%G
if %curuser% EQU [] exit

REM Get unused drive letters and select one at random
setlocal
setlocal enabledelayedexpansion
set "_DRIVE.LETTERS.FREE=Z Y X W V U T S R Q P O N M L K J I H G "
for /f "tokens=1,2 delims=: " %%a in ('netusetest.cmd') do (
set "_DRIVE.LETTERS.USED=!_DRIVE.LETTERS.USED!%%a"
set "_DRIVE.LETTERS.FREE=!_DRIVE.LETTERS.FREE:%%a =!"
)
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:~0,26%
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:,@=, @%
REM set _DRIVE.LETTERS

REM Get the string's length
set #=%_DRIVE.LETTERS.FREE%
set length=0
:loop
if defined # (
set #=%#:~1%
set /A length += 1
goto loop
)
set /A length="!length!/2"
set /A RANDVAR="%RANDOM%%%%length%"
for /f "tokens=%RANDVAR%" %%c in ("%_DRIVE.LETTERS.FREE%") do set
_source=%%c:

REM Setup Robocopy variables
SET _dest=\\BACKUPSERVER\Windows$\%curuser%\%computername%
SET _what=/COPYALL /B /SEC /MIR /XJ
SET _options=/NP /R:0 /W:0 /LOG:c:\Progra~1\Robocopy\robocopy.txt
SET _exclude=/XD "%_source%\AppData\Local\Temp" "%_source%\AppData
\Local\Microsoft\Windows\Temporary Internet Files" "%_source%\AppData
\Local\Google\Chrome\User Data\Default\Cache" "%_source%\AppData
\Roaming\Mozilla\Firefox\Profiles"
c:\windows\system32\eventcreate /ID 3 /L APPLICATION /T INFORMATION /
SO Wrkstbkpsrv /D "Shadow Copy Drive Letter selected. Robocopy
settings loaded. Beginning Server Ping & Overlap Check" > NUl

echo "%DATE% %time% - Checking for server" > "c:\Program Files\Robocopy
\robo_run.txt"
REM Check if Server can be found!
ping BACKUPSERVER.DOMAIN.local > NUl
if %errorlevel% NEQ 0 goto noserver
echo "%DATE% %time% - Ping ok" >> "c:\Program Files\Robocopy
\robo_run.txt"

REM Check if robocopy is running already!
FOR /F "usebackq tokens=1" %%i IN (`%SystemRoot%
\System32\tasklist.exe`) DO if /I "%%i"=="robocopy.exe" goto :eof >
NUl
echo "%DATE% %time% - Robocopy not running" >> "c:\Program Files
\Robocopy\robo_run.txt"

REM Check if shadowspawn is running already!
FOR /F "usebackq tokens=1" %%i IN (`%SystemRoot%
\System32\tasklist.exe`) DO if /I "%%i"=="ShadowSpawn.exe" goto :eof >
NUl
echo "%DATE% %time% - Shadowspawn not running" >> "c:\Program Files
\Robocopy\robo_run.txt"

REM Run ShadowSpawn then Robocopy
echo "%DATE% %time% - Running backup" >> "c:\Program Files\Robocopy
\robo_run.txt
@echo on
"c:\Program Files\Robocopy\ShadowSpawn.exe" c:\Users\%curuser% %_source
% "c:\Program Files\Robocopy\robocopy.exe" %_source% %_dest% %_what%
%_exclude% %_options%
@echo off

set roboerror=%errorlevel%
if %roboerror% EQU 2 echo "%DATE% %time% - Backup error: %roboerror%"
>> "c:\Program Files\Robocopy\robo_history.txt"
if %roboerror% NEQ 2 echo "%DATE% %time% - Backup completed" >> "c:
\Program Files\Robocopy\robo_history.txt"
echo "%DATE% %time% - Backup complete" >> "c:\Program Files\Robocopy
\robo_run.txt"
c:\windows\system32\eventcreate /ID 1 /L APPLICATION /T INFORMATION /
SO Wrkstbkpsrv /D "Backup Completed - Log saved to: c:\Program Files
\Robocopy\robo_run.txt" > NUl

net use %_source% "\\BACKUPSERVER\windows$"
copy /Y "c:\Progra~1\Robocopy\robo_history.txt" "Q:\%curuser%\
%computername%" > NUl
copy /Y "c:\Progra~1\Robocopy\robocopy.txt" "Q:\%curuser%\%computername
%" > NUl
net use %_source% /delete /yes
goto:eof

:noserver
c:\windows\system32\eventcreate /ID 2 /L APPLICATION /T INFORMATION /
SO Wrkstbkpsrv /D "Destination not found - Log saved to: c:\Program
Files\Robocopy\robo_run.txt" > NUl
goto:eof
EOF

The logs are stored in the \\BACKUPSERVER\%curuser%\%computername% for
review and some logs in c:\program files\robocopy

netusetest.cmd:
@echo off
FOR /F "usebackq skip=4 tokens=2 " %%I IN (`net use`) DO @echo %%I |
findstr :
EOF

driveletter.cmd:
@echo off & setlocal
setlocal enabledelayedexpansion
set "_DRIVE.LETTERS.FREE=Z Y X W V U T S R Q P O N M L K J I H G "
for /f "tokens=1,2 delims=: " %%a in ('test.cmd') do (
set "_DRIVE.LETTERS.USED=!_DRIVE.LETTERS.USED!%%a"
set "_DRIVE.LETTERS.FREE=!_DRIVE.LETTERS.FREE:%%a =!"
)
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:~0,26%
set _DRIVE.LETTERS.USED=%_DRIVE.LETTERS.USED:,@=, @%
REM set _DRIVE.LETTERS

REM Get the string's length
set #=%_DRIVE.LETTERS.FREE%
set length=0
:loop
if defined # (
set #=%#:~1%
set /A length += 1
goto loop
)
set /A length="!length!/2"
set /A RANDVAR="%RANDOM%%%%length%"
for /f "tokens=%RANDVAR%" %%c in ("%_DRIVE.LETTERS.FREE%") do set
DRIVE1=%%c
EOF

Cavets:
- It appears Shadowspawn & Robocopy will only work if you turn echo
on.
- I do a lot of drive letter checking because my users use all sorts
of letters to map the network shares. I try to be accommodating. Also
I noticed if my file server gets a bad drive (Drive times out) it
turns the shares to offline and the typical ways you check for mapped
network shares doesn't work and shows they are available when they
really are not.
- If anyone knows how to set via command line the task schedule
option: "delay task for up to (random delay):" just so all 50+ users
are not hitting the server at the same time...

Craig Andera

unread,
Oct 7, 2011, 10:04:43 AM10/7/11
to shadowsp...@googlegroups.com
> I figured since I wrote this for work for my 50 or so mobile Windows 7
> users and it's been working well I've release it for everyone. Time
> permitting I'll redo this in powershell. Probably be a one liner
> script :)

Very cool! Glad to hear that it is working well for you.

> Cavets:
> - It appears Shadowspawn & Robocopy will only work if you turn echo
> on.

Interesting. What's the failure mode when echo is not on? Is it
ShadowSpawn that fails or Robocopy? I.e. if you launch something other
than Robocopy, does it still work? We can look into this if it's a
ShadowSpawn issue.

Nathaniel

unread,
Oct 7, 2011, 10:47:31 AM10/7/11
to ShadowSpawn Support
I'll have to retest that. It was an error on robocopy that stated the
source didn't exist. However when I went to debug it by enabling
echoing at the script.cmd's root, everything worked. Since the echos
are captured to rolling logs I wasn't too concerned by it.

John Gray

unread,
Oct 7, 2011, 1:12:41 PM10/7/11
to ShadowSpawn Support
On Oct 7, 2:41 pm, Nathaniel <nbentzin...@gmail.com> wrote:
<snip>

> - If anyone knows how to set via command line the task schedule
> option: "delay task for up to (random delay):" just so all 50+ users
> are not hitting the server at the same time...

I assume you have already sampled the delights of
SCHTASKS /Create /?
?

I also back up both the AllUsers and <myname> profiles from my own PC
with RoboCopy, but I find I don't need to use ShadowSpawn for these;
about the only important RoboCopy switch I find I need is /XJ, eXclude
Junctions...

In your instance, have you considered just backing up the Roaming
Profiles which live on the server (assuming you use these)? I do this
overnight to a spare partition on a couple of PCs, as well as the
normal server backups..
Reply all
Reply to author
Forward
0 new messages