Ни для кого не секрет, что в любой компании пользователи приходят и уходят. Как итог - за пару лет пол сотни уволенных сотрудников, пачка пользователей в AD помеченных как "Неактивные"(Disabled) и загаженный их директориями терминальный сервер, который как известно далеко не резиновый.
"Удалять директории руками ежеминутно сверяясь с таблицей?" Решение, честно говоря, так себе.
Как итог: мной создан скрипт ниже, для перемещения всех неактивный пользователей. Как обычно - критика приветствуется.
На чём будем использовать:
1) Windows Server 2008R2 на котором у нас есть полноценный доступ к ActiveDirectory
2) Терминальный сервер Windows Server 2008R2 на котором данного доступа нет.
P.S.: В противном случае, если доступ к AD есть и с терминального сервера, можем радостно объединить части и выполнять всё ниже описанное там.
Часть 1: Выполняется на сервере с доступом к AD
Сначала получаем список активных пользователей ActiveDirectory:
import-module activedirectory #Загружаем модуль ActiveDirectory
$properties = @(
'SamAccountName'
'Enabled'
)
$ADUsersList = Get-ADUser -f {SamAccountName -like '*'} -Properties $properties | Select -Property $properties | Where-Object {$_.Enabled -eq "True"}
$ADUsersList | Out-Gridview
Часть 2: Выполняется непосредственно на терминальном сервере.
Для начала отступление: PowerShell имеет достаточно большое кол-во операторов сравнения, таких как -eq и -like, однако в случае сравнения двух массивов про эти операторы можно радостно забыть. Очень прилично эту тему в своё время осветил Vadims Podāns: https://www.sysadmins.lv/blog-ru/powershell-massivy-chast-2-poslednyaya.aspx
Оператор сравнения Compare-Object мне так же не подошёл. Как итог: пришлось писать функцию сравнения самому. Привожу ниже:
########################################### Initialization functions Massive Compare #######################
function MassiveCompare {
param (
[Parameter(Mandatory = $true,Position=0,HelpMessage="11")]
[Array] $FirstMassiv,
[Parameter(Mandatory = $true,Position=1,HelpMessage="22")]
[Array] $SecondMassiv,
[Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage='33333')]
[ValidateLength(4,7)]
[string]$Muching
)
begin {
}
process {
[Array] $MuchMassivElemetns = @()
[Array] $NotMuchMassivElemetns = @()
for ($FirstMassivIndex = 0; $FirstMassivIndex -lt $FirstMassiv.'length'; $FirstMassivIndex++) {
$matchValuesArraysFound = $false
for ($SecondMassivIndex = 0; $SecondMassivIndex -lt `
$SecondMassiv.'length'; $SecondMassivIndex++) {
if ($FirstMassiv[$FirstMassivIndex] -like [string]::Concat( `
$SecondMassiv[$SecondMassivIndex],'*')) {
$matchValuesArraysFound = $true
break
}
else {
#do nothing#
}
}
if ($matchValuesArraysFound -eq $true) {
$MuchElement = New-Object -TypeName PSObject
Add-Member -InputObject $MuchElement -MemberType NoteProperty `
-Name MuchElement_Name_FirstArray -Value $FirstMassiv[$FirstMassivIndex]
Add-Member -InputObject $MuchElement -MemberType NoteProperty `
-Name MuchElement_Name_SecondArray -Value $SecondMassiv[$SecondMassivIndex]
$MuchMassivElemetns += $MuchElement
}
if ($matchValuesArraysFound -eq $false) {
$NotMuchElement = New-Object -TypeName PSObject
Add-Member -InputObject $NotMuchElement -MemberType NoteProperty `
-Name NotMuchElement_Name -Value $FirstMassiv[$FirstMassivIndex]
$NotMuchMassivElemetns += $NotMuchElement
}
}
}
end {
if ($Muching -like 'Much') {
return $MuchMassivElemetns
}
if ($Muching -like 'NotMuch') {
return $NotMuchMassivElemetns
}
}
}
#############################################################################################################
Как итог на выходе:
MassiveCompare $Массив№1 $Массив№2 -Muching NotMuch # Получаем все не совпавшие элементы
MassiveCompare $Массив№1 $Массив№2 -Muching Much # Получаем все совпавшие элементы
Далее нам необходима функция перемещения директорий в необходимое нам место:
########################################### Initialization functions Move Directories ######################
function MoveDir {
param (
[Parameter(Mandatory = $true,Position=0,HelpMessage="11")]
[Array] $DirNameList,
[Parameter(Mandatory=$True, Position=1,ValueFromPipeline=$false, HelpMessage='22222')]
[ValidateLength(3,50)]
[string]$OldPath,
[Parameter(Mandatory=$True, Position=2,ValueFromPipeline=$false, HelpMessage='33333')]
[ValidateLength(3,50)]
[string]$NewPath
)
begin {
$MoveDirQuantity = $DirNameList.Length
$report = @()
}
process {
for ($MoveDirIndex = 0; $MoveDirIndex -lt $MoveDirQuantity; $MoveDirIndex++) {
$SelectFolderName = $DirNameList[$MoveDirIndex]
$SelectFolderOldPath = "$OldPath\$SelectFolderName"
$SelectFolderNewPath = "$NewPath\$SelectFolderName"
Move-Item -LiteralPath $SelectFolderOldPath -destination $NewPath
$ReportMoveDirObject = New-Object -TypeName PSObject
Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
-Name Moved_Folder_Name -Value $SelectFolderName
Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
-Name Old_Folder_Path -Value $SelectFolderOldPath
Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
-Name New_Folder_Path -Value $SelectFolderNewPath
$report += $ReportMoveDirObject
}
}
end {
return $report
}
}
#############################################################################################################
Как итог: получаем достаточно удобный в использовании инструмент по перемещению директорий + чёткий репорт на выходе содержащий: что, откуда и куда было перемещено.
Синтаксис: MoveDir $Массив_имён_директорий_для_перемещения $Откуда $Куда
Поехали далее:
Инициализируем первый объект массив . Заполняем его именами всех директорий из C:\Users
$ListTermSRVDirUsers = Get-ChildItem $TermUsersFolderPath | ?{$_.PsIsContainer -eq $true}
Инициализируем второй объект массив. Заполняем его имена активных пользователей AD.
$ListADUsers = @(
#Массив имён активных пользователей из AD
)
Используем ранее написанную функцию по сравнению двух массивов для выявления не совпавших элементов.
$NeedMoveUsersDirTermSRV = MassiveCompare $ListTermSRVDirUsers $ListADUsers -Muching NotMuch
$NeedMoveDirNameList = $NeedMoveUsersDirTermSRV | foreach {
$_.NotMuchElement_Name
}
Не забывайте, что директория пользователей на терминальном сервере, содержит ещё и служебные директории, такие как Default, Public и т.д.
Их перемещение может вызвать нежелательные последствия. В связи с этим, нам необходимо пометить данные директории как запрещённые к перемещению. Директорию DeletedUsers, в которую мы перемещаем директории неактивных пользователей так же нужно исключить.
Поэтому:
Инициализируем ещё один массив с именами директорий запрещённых к перемещению и повторно прогоняем через функцию сравнения массивов, получая на выходе не совпавшие элементы.
$ForbiddenMoveUsersDirTermSRV = @(
'DeletedUsers'
'Public'
'e18070'
'Default'
)
Write-Output ("`n`Исключаю запрещённые к перемещению директории:")
Write-Output ("`n`t$ForbiddenMoveUsersDirTermSRV")
Write-Output ("`n`_________________________________________________________________________________________")
$NeedMoveDirExcludeForbiddenTermSRV = MassiveCompare $NeedMoveDirNameList $ForbiddenMoveUsersDirTermSRV `
-Muching NotMuch
$NeedMoveDirExcludeForbiddenNameList = $NeedMoveDirExcludeForbiddenTermSRV | foreach {
$_.NotMuchElement_Name
}
Далее используя полученный массив имён прогоняем через функцию перемещения директорий. Репорт выводим в формате таблицы.
MoveDir $NeedMoveDirExcludeForbiddenNameList $TermUsersFolderPath $DeletedUsersFolderPath | FT
$host.ui.RawUI.ReadKey(6)|out-null