As many know, in the properties of replicated folders, you can configure exceptions in the form of file masks - and then the service will not replicate files that match the specified masks. But not everyone knows that files have a “temporary” attribute, and DFSR does not handle such design files. And if this is not taken into account, it may happen that the contents of your DFSR folders become unsynchronized, although in the service logs everything will be clean and beautiful, and it may emerge at the most inopportune moment. The problem itself and its solution have already been dealt with on the Internet more than once; the goal of this article is to modify the solution created earlier, adding flexibility and convenience to it. For whom it is important - I ask under the cat.
The topic has been covered on the Internet for a long time and more than once, for example in the
official blog ,
here and
on Habré itself . Therefore, I will not repeat, but let me get straight to the point. The original solution is a PowerShell script that resets the “temporary” attribute for all files in a given folder. Taking it as a basis, I wrote my own version, which finds the replicated folders on the target server and goes over each of them, resetting the problem attribute, and then sends a report on the files found by email. Support for
long paths is also added (5th version of PowerShell is required).
The script requires DFS services management tools (installed by default with the addition of the DFS Replication role). If they are missing on the target server, run this cmdlet:
Install-WindowsFeature RSAT-DFS-Mgmt-Con
But the script itself:
')
TempAttrFixer.ps1 Param( # [parameter(Mandatory=$false)][String]$OutDir ) $SMTPServer = "mail.mydomain.com" $MailFrom = "sender@mydomain.com" $MailTo = "recipient@mydomain.com" Function ConvertTo-LiteralPath { # LiteralPath Param( [parameter(Mandatory=$true)][String]$Path ) # UNC If ($Path.Substring(0,2) -eq "\\") { Return ("\\?\UNC" + $Path.Remove(0,1)) } Else { Return "\\?\$Path" } } $StartTime = Get-Date $Error.Clear() If (!$OutDir) { $OutDir = (Get-WmiObject Win32_OperatingSystem).SystemDrive +"\TempAttrFixer_Report" } # , $FoldersToScan = @(Get-DfsrMembership -ComputerName $env:COMPUTERNAME | Sort-Object GroupName, FolderName).ContentPath $LogFileName = "$env:COMPUTERNAME" + "_TempFiles_" + (Get-Date -Format "yyyy-MM-dd-HH-mm-ss") + ".csv" $LogFilePath = "$OutDir\$LogFileName" $Delimiter = "`t" $FilesCount = 0 If (!(Test-Path $OutDir -PathType Container)) { New-Item -ItemType Directory -Force -Path $OutDir | Out-Null } ForEach ($Folder in $FoldersToScan) { # PowerShell 5.1, LireralPath Write-Output "Scanning `"$Folder`"..." Get-ChildItem -LiteralPath (ConvertTo-LiteralPath $Folder) -Recurse | ForEach-Object -Process { if (($_.Attributes -band 0x100) -eq 0x100) { $FilesCount += 1 $Entry = $_.FullName + $Delimiter + $_.GetAccessControl().Owner + "`r`n" $Entry $Entry | Out-File -FilePath $LogFilePath -Encoding unicode -Append -NoNewline $_.Attributes = ($_.Attributes -band 0xFEFF) } } } $FinishTime = Get-Date $TimeSpan = $FinishTime - $StartTime Write-Output ("Done, errors: " + $Error.Count) $Encoding = [System.Text.Encoding]::Unicode If ($FilesCount -gt 0) { $MessageBody = $null $Subject = " " $MessageBody += " : $env:COMPUTERNAME`r`n" $MessageBody += " : " + $TimeSpan.ToString() + "`r`n" $MessageBody += " `"$LogFilePath`"`r`n" Send-MailMessage -SmtpServer $SMTPServer -From $MailFrom -Subject $Subject -Encoding $Encoding -To $MailTo -Body $MessageBody -Attachments $LogFilePath } Else { $MessageBody = $null $Subject = " " $MessageBody += " : $env:COMPUTERNAME`r`n" $MessageBody += " : " + $TimeSpan.ToString() + "`r`n" Send-MailMessage -SmtpServer $SMTPServer -From $MailFrom -Subject $Subject -Encoding $Encoding -To $MailTo -Body $MessageBody } #, - If ($Error.Count -gt 0) { $MessageBody = $null $Subject = " " $MessageBody += " : $env:COMPUTERNAME`r`n" $MessageBody += " : $env:UserName`r`n" $MessageBody += " :`r`n" $MessageBody += $Error[0] Send-MailMessage -SmtpServer $SMTPServer -From $MailFrom -Subject $Subject -Encoding $Encoding -To $MailTo -Body $MessageBody }
Edit the values of the variables responsible for email alerts and add the script to the scheduler:
powershell.exe -NoLogo -ExecutionPolicy Bypass -NoProfile -File "< >\TempAttrFixer.ps1"
It is easiest to run a task from SYSTEM, but if you have
an increased level of paranoia and you practice a serious approach to information security, you can use a separate account by giving it a login privilege as a batch job and the right to modify files in replicated folders.
Instead of email reports (or in addition to them), you can configure the script to interact with a zabbiks or other monitoring system. It is also important to understand that the procedure is quite resource-intensive, so do not run it too often. It takes us about an hour to process 10TB of data, and the script runs once a day at night.
Also, my colleagues and I were interested in the question of where the files with the temporary-attribute come from. Therefore, each report along with the full file name appears its NTFS owner. Based on the collected data, we managed to find out that in our situation an attribute was sometimes added to the files when copying data from local disks routed through RDP (we are actively using remote desktops technology). But it is possible that the files were initially "defective." It was not possible to find out in more detail.
I would be grateful if you pass a short survey and share your experiences in the comments.