Moving data / shares to another file server

I am looking for the best way to move data from one file server to another.. and then using the share on the new server as the main file server.

I want to have an exact copy of old server on the new server even tho people are still saving to the old server

My last step to switch end users over is a edit of the login script to point to new server

I want the same permissions to carry over to the new server

How can I achieve this? Looking for a simply solution.

At first I was going to backup old server - restore to new server and then switch over, but then I had to worry about people saving to the old server and the data not not being the same after the restore.
GorapsI.T. ManagerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Best to use RoboCopy:
robocopy \\oldserver\share \\newserver\share /MIR /R:1 /W:5 /CopyAll /DCopy:T

Open in new window

This can be run as often as you like, and will only apply changes to the new location (including deleting files no longer at the source).
You can't move the share info itself; this needs to be done manually once on the new server.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
GorapsI.T. ManagerAuthor Commented:
can I test this by selecting a sub folder within the share?

robocopy \\oldserver\share\subfolder  \\newserver\share\subfolder  /MIR /R:1 /W:5 /CopyAll /DCopy:T
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Yes, of course. Try it with one or two subfolders. The results will be kept if you do the parent folder.
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

Jose TorresSenior SQL Server DBACommented:
There could be other ways to accomplish this.

We recently migrated one of our 2003 production finance file servers to a new 2008r2 server (NO FSRM).
These were the steps that we conducted

Note: Depending on the backup/restore software you use you might be able to retain the Share Permissions after the restore.  You will definitely retain the NTFS permissions

Assumption: You are taking at least a daily full backup of the server.

Pre-production tasks
1. Configured the new file server.
2. Did a redirected restore (data folders only) to the new server.
3. Created the network shares (see the code further below for export and import).
4. Turned server over for smoke testing

Production tasks
Note: Since we handle the creation of shares on the server we would now if any new shares were created since the time that the export/import was done and apply those new ones if any.
1. In the morning (after the backups have completed)
     a. Restore (data folders only) to new server with last full backup
     b. Restore (data folders only) to new server with last differential (if you are taking diffs)
2. After business hours.  Users should have already been informed ahead of time that the system will be unavailable for this upgrade.
     a. Perform an Incremental backup (data folders only) of the old server
     b. Restore the (data folders only) using the new incremental backup
     c. Take the old server of the domain
     d. Create a CNAME for the old server to point to the new server.
     e. Test you can access the shares on the new server using both old server and new server.
          Note: It may take a few minutes for the new names to replicate to all the domain controlers
     f. Contact identified individuals to test access.
3. Go have a beer it's been a long day.

This is the code for the export change backup location to suit your needs
# change to the servername to be used. (currently set to get local computer name)
$ServerName = $Env:COMPUTERNAME

# get the current timestamp
$Date = Get-Date -Uformat '%Y%m%d%H%M%S'
# setup the filename
$FileName = 'C:\DisasterRecovery\Backup_Shares\Backups\' + 'Backup_' + $ServerName + '_ShareInfo_' + $Date + '.csv' 

# get Shares (Type o is "Normal" shares) 
$Shares = Get-WmiObject Win32_Share -ComputerName $ServerName -Filter 'type=0' 

# combine Shares with Security info 
$ShareInfo = @() 
Foreach ($share IN $Shares) { 
	$shareSec = Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $ServerName -Filter "name='$($'" 
  	IF($shareSec) { 
    	$sd = $shareSec.invokeMethod('GetSecurityDescriptor',$null,$null) 
    	$ShareInfo += $sd.Descriptor.DACL |% { 
      		$_ | select @{e={$};n='Name'}, 
		$ShareInfo += $share | select Name,Path,Description 

# Export the shares to CSV 
$ShareInfo | select Name,Path,Description,User,Domain,SID, 
  AccessMask,AceFlags,AceType | export-csv -noType $filename

Open in new window

This is the code for the Import. I run this from a batch file so you will need to modify the $fname and remove the param section of the script. Also change the filename path accordingly.
# get argument passed by cmd
	[Parameter(Mandatory=$true)] [string] $fname,
	[Parameter(ValueFromRemainingArguments=$true)] $args
# check if more than 1 argument was passed
if ($args) {
	Write-Host "ERROR: Unknown argument(s): $args"
	Exit 2
# set filename and path
$FileName = 'C:\DisasterRecovery\Backup_Shares\Backups\' + $fname
# check if file exists
if (!(Test-Path $FileName)) {
	Write-Host "ERROR: File $FileName does not exist."
	Exit 3


# Functions used in script #

Function Modify-WMIShareACL([string]$ServerName, [string]$ShareName, $ace){
    $wPrivilege = Get-WmiObject Win32_LogicalShareSecuritySetting -ComputerName $ServerName -filter "name='$ShareName'" 
    $wPrivilege.psbase.Scope.Options.EnablePrivileges = $true 
    $oldDACL = ($wPrivilege.GetSecurityDescriptor()).Descriptor.DACL 
    $sd = ([WMIClass] ("\\" + $ServerName + "\root\CIMv2:Win32_SecurityDescriptor")).CreateInstance()     
    $sd.DACL = $oldDACL #copy
    $sd.DACL += @($ace.psobject.baseobject) # append
    $sd.ControlFlags="0x4" # set SE_DACL_PRESENT flag 

Function Create-WMITrustee ([string]$ServerName, [string]$ShareUser, [string]$ShareSID){
	$sid = New-Object Security.Principal.SecurityIdentifier($ShareSID)
	[byte[]]$ba = ,0 * $sid.BinaryLength     

	$Trustee = ([WMIClass] ("\\" + $ServerName + "\root\CIMv2:Win32_Trustee")).CreateInstance() 
    $Trustee.SID = $ba

Function Create-WMIAce ([string]$ServerName, [string]$ShareUser, [string]$ShareSID, [string]$ShareAccessMask, [string]$ShareAceFlags, [string]$ShareAceType){
	$Trustee = Create-WMITrustee $ServerName $ShareUser $ShareSID
	$ace = ([WMIClass] ("\\" + $ServerName + "\root\CIMv2:Win32_ACE")).CreateInstance() 
	$ace.AccessMask = $ShareAccessMask
	$ace.AceFlags = $ShareAceFlags
	$ace.AceType = $ShareAceType
	$ace.Trustee = $Trustee


# change to the servername to be used. (currently set to get local computer name)
$ServerName = $Env:COMPUTERNAME

# Import the CSV file 
$ShareList = Import-Csv $FileName 


# get the unique shares 
$UniqueShares = $ShareList | select -Unique name, Path, Description
# go thru each unique share
Foreach ($ushare in $UniqueShares) {
	$ShareName = $
	$SharePath = $ushare.Path
	$ShareDesc = $ushare.Description
	# check if path exists
	if (!(Test-Path $SharePath)) {
		Write-Host "ERROR: Path $SharePath DOES NOT EXIST"
		Exit 5
	# create share if it does not exist
	if (!(Get-WmiObject Win32_Share -ComputerName $ServerName | Where-Object -FilterScript {$_.Name -eq $ShareName})) {
		# create pointer to Win32_Share
		[WMIClass]$cshare = "\\$ServerName\root\CIMv2:Win32_Share"
		# create share
		$rc = $cshare.Create($SharePath, $ShareName, 0, 0, $ShareDesc)
		# get description or rc value
		Switch ($rc.returnvalue){
			0  {$rvalue = "Success"}
			2  {$rvalue = "Access Denied"}
			8  {$rvalue = "Unknown Failure"}
			9  {$rvalue = "Invalid Name"}
			10 {$rvalue = "Invalid Level"}
			21 {$rvalue = "Invalid Parameter"}
			22 {$rvalue = "Duplicate Share"}
			23 {$rvalue = "Redirected Path"}
			24 {$rvalue = "Unknown Device or Directory"}
			25 {$rvalue = "Net Name Not Found"}
		# check return value of create
		if ($rc.returnvalue -ne 0){
			Write-Host ("ERROR: Failed to create share {0} for {1} on {2}. Error: {3}" -f $ShareName, $SharePath, $ServerName, $rvalue)
			Exit 6

Foreach ($record in $ShareList) {
	$ShareName = $record.Name
	$SharePath = $record.Path
	$ShareDesc = $record.Description
	$ShareUser = $record.User
	$ShareDomain = $record.Domain
	$ShareSID = $record.SID
	$ShareAccessMask = $record.AccessMask
	$ShareAceFlags = $record.AceFlags
	$ShareAceType = $record.AceType
	$ace = Create-WMIAce $ServerName $ShareUser $ShareSID $ShareAccessMask $ShareAceFlags $ShareAceType
	Modify-WMIShareACL $ServerName $ShareName $ace

Open in new window

Jose TorresSenior SQL Server DBACommented:

We did want to go with the robocopy approach but due to the large volume of data that would have to go through the network made this option not as feasible as we would have preferred.

But it is a very good option
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
You can slow down or speed up the process by using /IPG:n (inter-packet gap in ms) or /MT (multi-threaded). for the first run. You can also write a small script to go thru the first level of subfolders and copy those individually (and then add /secfix in the final copy, to make sure security is transferred correctly). There are a lot of options.

The only issue I see is that the servers need to be on a fast network connection. Otherwise I would use a backup for the basic (first) copy, and then robocopy to apply changes.
GorapsI.T. ManagerAuthor Commented:
Is there anyway for it to spit off a log once it's completed with errors / successful
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
/log:filename.txt will create a new log file, /log+:filename.txt append to an existing.
GorapsI.T. ManagerAuthor Commented:
I've been testing this out... It seems to take the same amount of time regardless if it's first time copying vs. incremental copy.  and some fails have fails / been skipped without explanation.
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
With a lot of files and big amount to copy you should see a significant time difference. /secfix however will require to change all files, and that again increases the time for an incremental copy.
Skipped files are in use, or otherwise locked, or have security applied which denies access.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Windows Server 2008

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.