. Причем это не потребует написания сценариев. Все, что я собираюсь показать, потребует всего несколько интерактивных команд. Конечно, если вам придется запускать эти команды часто, сохранить их в виде сценария или функции будет логично.

Особенность Powershell заключается в том, что вы можете взять результаты команд, которые я собираюсь показать, и сделать с ними все, что захотите. Необходимо сохранить результат в файл. csv? Используйте Export-CSV. Нужен отчет в формате HTML? Вам поможет ConvertTo-HTML. Кроме того, все, что я собираюсь продемонстрировать, масштабируется; если вы можете применить команду для одного компьютера, она может быть использована для 10, 100 или 1000 систем.

Сначала я покажу вам, как управлять тем, что уже находится в общих папках. Затем мы рассмотрим процесс создания и удаления общих папок.

Получение списка общих папок

Давайте начнем с определения того, что находится в общих папках. Просто создайте запрос к классу Win32_Share инструментария управления WMI. Вам даже не нужно регистрироваться на файловом сервере, вы можете запустить эту команду со своего рабочего места:

Get-WmiObject -class -Win32_Share -computernameMyFile

После выполнения данной команды вы получите список общих ресурсов, включая принтеры (если они есть). Поскольку мы говорим об общих файловых ресурсах, давайте изменим запрос соответствующим образом. Каждый объект Win32_Share имеет свойство «Тип», см. таблицу. Таким образом, чтобы ограничить наш запрос, мы можем добавить фильтр к первоначальной команде.

Get-WmiObject -class -Win32_Share -computernameMyFile–filter«Type=0»

 

Типы общих ресурсов и их свойства

Таким образом, мы исключили административные общие ресурсы. Это можно увидеть на экране 1.

 

Вывод неадминистративных общих ресурсов с?помощью WMI
Экран 1. Вывод неадминистративных общих ресурсов с? помощью WMI

Для получения списка скрытых общих ресурсов – тех, что заканчиваются значком доллара ($), — вам нужно лишь немного изменить фильтр:

Get-WmiObject -Class win32_share -computernameMyFile –filter «Type=0 AND name like '%$'»

В WMI символ % используется как знак подстановки. Поэтому получить список общих ресурсов, за исключением скрытых, немного сложнее, нам потребуется сравнение с использованием подстановочного символа:

Get-WmiObject -Class win32_share -computernameMyFile–filter «type=0 AND name like '%[^$]'»

Эта команда возвращает все объекты Win32_Share, у которых свойство «Тип» равно 0 и имя не заканчивается на $.

Определение размера папки

Одной из типичных задач администратора является создание отчетов о том, как много места занимает папка. Быстрый способ — задействовать команду Get-ChildItem, или ее псевдоним (alias) dir, и перенаправить вывод в Measure-Object:

dir c:sharespublic -recurse | where {-Not $_.PSIsContainer}|
Measure-Object -Property length -Sum -Minimum –Maximum

В результате вы получите объект, который показывает общее количество элементов, общий объем в байтах, наименьший и наибольший файлы. В предыдущей команде я исключил папки. В Powershell 3.0 предусмотрен лучший способ сделать это, но команда, которую я использовал, работает как в Powershell 2.0, так и в Powershell 3.0. Эта команда относится к тому типу, который лучше запускать локально (хороший повод удаленно использовать Powershell). Код в Листинге 1 задействует эту команду совместно с нашим механизмом WMI для получения отчета о размере папок верхнего уровня. Вы можете форматировать или обрабатывать $results так, как хотите. Как насчет удобной для чтения таблицы? Просто используйте команду:

$results | Format-Table Computername,Fullname,SizeKB,NumberFiles -autosize

На экране 2 показан приблизительный результат.

 

Вывод в виде таблицы
Экран 2. Вывод в виде таблицы

Для создания полного отчета об используемом дисковом пространстве для всех общих файловых ресурсов не потребуется много усилий. Я сэкономлю ваше время: взгляните на листинг 2. Как и в прошлый раз, я могу отформатировать $results так, как хочу. Результат использования этой техники показан на экране 3.

 

Отчет об использовании дискового пространства на файловом сервере
Экран 3. Отчет об использовании дискового пространства на файловом сервере

Получение списка файлов по владельцу

Другая вариация на эту тему — поиск файлов по их владельцу. Если вы применяете квоты, то вероятно уже составляете отчеты об их использовании. Если нет, то все, что вам нужно, это получить список управления доступом ACL для файла, который включает владельца, и обработать результаты. Мне кажется, лучший способ — это добавить владельца как настраиваемое свойство:

$data=dir | where {-not $_.PSIsContainer} |
select name, @{Name=«Owner»;Expression={(Get-ACL $_.fullname).Owner}}, length

Мы можем сгруппировать полученный результат по владельцу, а затем обработать полученный объект.

$data | group owner | Select Name,Count,@{Name=«Size»;Expression=
{($_.Group | Measure-Object -Property Length -sum).Sum}}

Приложив лишь немного усилий, вы сможете использовать эту же технику и для общих файловых ресурсов, как это делает код, указанный в листинге 3. Также необходимо отметить, что вы можете столкнуться с проблемами, если длина пути к файлу превышает 260 символов или если имена файлов содержат необычные символы, особенно при выполнении команды Get-Acl. В Powershell 3.0 эта команда поддерживает параметр – LiteralPath, который поможет в данном случае.

Нужно признать, что некоторые из приведенных примеров требуют набора довольно большого количества текста, и это не единственный способ выполнения задач, но они демонстрируют, что вы можете сделать. Для разовых отчетов можно обойтись меньшей детализацией. На экране 4 показан пример кода, который представляет результаты в виде таблицы.

 

Разовый отчет
Экран 4. Разовый отчет

Получение файлов по возрасту

Последний прием, который я хочу продемонстрировать, это составление отчетов, основанных на времени создания файлов. На самом деле мы создаем коллекцию объектов, которую можем в дальнейшем использовать несколькими способами. Вы можете задействовать эти объекты для удаления или перемещения файлов или для создания отчета, который затем можно отправить руководству по электронной почте. Всегда составляйте команды Powershell, держа в уме их повторное использование в дальнейшем.

Определение возраста файла — нетривиальная задача. В Powershell объект «файл» имеет несколько свойств, которые вы можете использовать. Например:

get-item c:workwishlist.txt | Format-List Name,*time

выводит результат, показанный на экране 5.

 

Свойства файла
Экран 5. Свойства файла

Лично мне свойство LastWriteTime кажется наиболее подходящим для определения времени, когда предоставлялся доступ к файлу. Мне встречались ситуации, когда свойство LastAccessTime обновлялось сторонним приложением, например антивирусом, что может приводить к ошибочным заключениям. Кроме того, LastAccessTime по умолчанию отключено со времен WindowsVista, но вы можете включить его. Нужно быть осторожным, так как значения этих свойств могут меняться, в зависимости от того, копируете вы или перемещаете файлы с тома на том. Однако окончательное решение остается за вами. Используя данный файл в качестве примера, мы можем с помощью Powershell определить возраст файла, как показано в листинге 4.

Параметр Age — это объект типа TimeSpan, а параметр Days — это просто значение параметра TotalDays данного объекта. Поскольку мы можем выполнить эту процедуру для одного файла, можем и для всех файлов. Давайте взглянем на мой общий ресурс Public и найдем все файлы, которые не изменялись 400 дней.

dir c:sharespublic -recurse | Select Fullname,CreationTime,LastWriteTime,
@{Name=«Age»;Expression={(Get-Date)-$_.LastWriteTime}},
@{Name=«Days»;Expression={[int]((Get-Date)-$_.LastWriteTime).TotalDays}},
@{Name=«Owner»;Expression={(Get-ACL $_.fullname).Owner}} |
Where {$_.Days -ge 400} | Sort Days –Descending

Я продолжил и включил владельца файла. На экране 6 показан результат выполнения этого кода в удаленной сессии на моем сервере.

 

Выполнение кода в удаленной сессии
Экран 6. Выполнение кода в удаленной сессии

Я мог сохранить эти результаты в переменную и использовать их повторно по своему усмотрению. Поскольку у меня было полное имя файла, перенаправление переменной в такую команду, как, например, Remove-Item, не составило бы труда.

Еще один подход — создание отчета или коллекции объектов. Для этого потребуется немного больше усилий; после того, как мы посчитаем или определим возраст элемента, потребуется добавить немного логики, чтобы что-нибудь с ним сделать.

Одна из моих любимых техник — это выяснение, сколько файлов было изменено с группировкой по годам (экран 7). И снова для демонстрации я буду использовать интерактивную удаленную сессию на своем файловом сервере.

dir c:sharessales -recurse | Select Fullname,LastWriteTime,
@{Name=«Age»;Expression={(Get-Date)-$_.LastWriteTime}},
@{Name=«Year»;Expression={$_.LastWriteTime.Year}} |
Group-Object Year | Sort Name

 

Поиск времени последнего изменения файлов с?группировкой по годам
Экран 7. Поиск времени последнего изменения файлов с?группировкой по годам

Если мне понадобится больше деталей, то я всегда могу проанализировать параметр Group, который является набором файлов.

Может пригодиться информация о том, сколько файлов не изменялись за последние 30, 90 или 180 дней. К сожалению, нет простого способа использовать для этого Group-Object, поэтому мне пришлось решать задачу «в лоб», как показано в листинге 5. На экране 8 показан результат, который получился в результате обработки этим кодом моей папки со сценариями, в которой, как я знал, располагаются файлы различного «возраста». Мой код не выводит сами файлы, но модифицировать его будет несложно.

 

Дата последнего изменения файлов
Экран 8. Дата последнего изменения файлов

Создание общих файловых ресурсов

Теперь давайте посмотрим, как можно использовать Powershell для создания общих файловых ресурсов и управления ими. Все, что я продемонстрировал до настоящего момента, будет работать как в Powershell 2.0, так и в Powershell 3.0 (хотя при использовании Powershell 3.0 мои примеры в некоторых местах можно упростить). Управление файловым сервером с помощью Powershell 2.0 требует применения WMI и написания сложных сценариев. Но в Powershell 3.0, особенно если вы используете Windows Server 2012, этот тип управления реализован очень удачно. Я собираюсь переключить передачу и управлять файловым сервером на базе WindowsServer 2012 с компьютера с установленной Windows 8. Таким образом, мне будут доступны некоторые дополнительные функции.

Все, что нам нужно, встроено в модуль SMBShare, который устанавливается в Windows 8 по умолчанию. Команды, входящие в этот модуль, позволяют с легкостью управлять общими файловыми ресурсам как на локальных, так и на удаленных серверах. Я не буду рассматривать каждую команду, но все они имеют схожий формат, и я настоятельно рекомендую прочитать подсказку и просмотреть примеры. Мы начнем с использования команды New-SMBShare, для того чтобы создать новый общий файловый ресурс.

Нам нужно указать путь к папке и, в отличие от того, как это происходит в случае использования графического интерфейса, команда не создает папку, если она не существует. Поэтому мы создадим ее и назначим разрешения NTFS. Это процедура состоит из нескольких шагов. Поскольку их нужно выполнить на удаленном сервере, я создам удаленную сессию Powershell.

$session=New-PSSession -ComputerName SRV2K12RC

Я мог бы использовать эту сессию интерактивно, но я собираюсь запускать команды, используя Invoke-Command, которые более предпочтительны, когда вы настраиваете автоматический процесс. Я создам новую папку:

invoke-command -ScriptBlock {mkdir c:sharescompanyfiles} -Session $session

Теперь более сложная часть. Я хочу назначить разрешения NTFS так, чтобы группа JDHLABDomainUsers имела разрешения на изменения Change. Для этого потребуется создать новое правило доступа, изменить список правил доступа и применить измененный список к папке. Я написал эту команду так, что она использует параметр в качестве пути, что делает возможным ее повторное использование:

Invoke-Command -ScriptBlock $sb -Session $session –ArgumentList
c:sharescompanyfiles

Существует возможность ускорить этот процесс, но для ясности я предпочитаю выполнять каждый шаг отдельно. Теперь мы можем создать общую папку.

Я мог бы использовать существующую удаленную сессию, но мне хотелось продемонстрировать, что команду New-SmbShare можно задействовать для подключения к удаленному файловому серверу.

New-SmbShare -Name Files -Path c:sharescompanyfiles
-CimSession SRV2K12RC -FullAccess «jdhlabdomain admins»
-ChangeAccess Everyone -Description «Company files»

По умолчанию на общий ресурс предоставляются разрешения на чтение ReadOnly. Я предоставил администратором домена полные разрешения FullControl, а всем остальным разрешения на изменения Change. Путь, указанный в параметре path, локальный для удаленного компьютера, на котором должен быть установлен Powershell 3.0

Дополнительные параметры общего ресурса

Мы можем в любое время просмотреть свойства общего ресурса, используя команду Get-SMBShare, как показано на экране 9.

 

Использование команды Get-SMBShare для?просмотра свойств общей папки
Экран 9. Использование команды Get-SMBShare для? просмотра свойств общей папки

Я применил изменения к одной общей папке, но было бы также просто с помощью Get-SMBShare получить список всех общих папок и затем с помощью Set-SMBShare применить изменение ко всем.

Get-SMBShare -CimSession SRV2K12RC -Special $False |
Set-SmbShare -EncryptData $True -Confirm:$false

Эта команда получает список всех общих папок (за исключением административных) на сервере SRV2K12RC и устанавливает значение параметра EncryptData, равное True. Мне не хотелось подтверждать каждое изменение, поэтому я установил значение ключа –Confirm равным False. Set-SMBshare ничего не передает дальше по конвейеру, если только не указать параметр –Passthru. Но мне удалось изменить сразу все одной простой командой.

Удаление общих папок

Последнее, что осталось рассмотреть, это удаление общих папок. Код в листинге 8 удаляет общий ресурс, который я только что создал. Может ли быть что-то проще? Конечно, сама папка осталось на сервере нетронутой.

Собираем все вместе

Давайте завершим наш обзор, собрав все части процесса управления в одном месте: рабочем процессе PowerShell Workflow. Я не могу в одной статье описать это огромное дополнение Powershell или приводить примеры кода, но должен сказать, что самое замечательное в Powershell Workflow то, что несколько команд могут выполняться параллельно. Например, после создания папки можно создать общий ресурс и назначить разрешения NTFS, см. листинг 9.

Этот процесс создает новую папку и новый общий ресурс, назначает права пользователю или группе. Я могу запустить его на своем компьютере с Windows 8, чтобы он отработал на удаленном сервере с WindowsServer 2012, следующей командой (ее нужно вводить одной строкой)

New-FileShare -Name adeco`
-Path c:sharesadeco `
-Principal jdhlabadeco `
-Right «FullControl» `
-PSComputerName SRV2K12RC

Выполнение занимает всего несколько секунд. Результат показан на экране 10.

 

Создание общей папки с помощью Powershell Workflow
Экран 10. Создание общей папки с помощью Powershell Workflow

Нет ничего плохого в использовании графического интерфейса для управления файловыми серверами. Но если вам нужны специальные отчеты или автоматизация, Powershell — лучшее, что может быть.

Если у вас есть вопросы по поводу этих примеров (или другие вопросы относительно Powershell), воспользуйтесь форумами на PowerShell.org.

Листинг 1. Получение отчета о размере папок верхнего уровня

$share=Get-WmiObject -Class Win32_Share -ComputerName
CHI-FP01 -filter «name='Sales'»
$sb={
Param ($path)
dir $path | where {$_.PSIscontainer} |
foreach {
$stats=dir $_.Fullname -recurse -errorAction
«SilentlyContinue» | where {-NOT $_.PSIscontainer} |
Measure-object -Property Length -sum
New-Object -TypeNamePSObject -Property @{
Computername=$env:Computername
Path=$_.Name
Fullname=$_.Fullname
SizeKB=[math]::Round(($stats.sum/1KB),2)
NumberFiles=$stats.count
} #property
} #foreach
} #sb
$results=Invoke-Command -ScriptBlock $sb -ComputerName
$share.__SERVER -ArgumentList@($share.path)
-HideComputerName

Листинг 2. Создание отчета об использовании общих ресурсов на файловом сервере

$sb={
#Get the file shares locally.
$shares=Get-WmiObject -Class Win32_Share -filter «type=0»
foreach ($share in $shares) {
#Suppress any access denied error messages.
Write-Host «Measuring $($share.path)» -ForegroundColor Green
$stats=dir $share.path -Recurse -ErrorActionSilentlyContinue |
Where {-Not $_.PSIscontainer} |
Measure-Object -Property Length -Sum
$hash=@{
Computername=$env:Computername
Path=$share.path
Share=$share.Name
SizeKB=[math]::Round(($stats.sum/1KB),2)
Files=$stats.count
}
#Write a custom object to the pipeline for each share.
New-Object -TypeNamePSObject -Property $hash
} #foreach $share
}#sb
$results = Invoke-Command -ScriptBlock $sb -ComputerName
CHI-FP01 -HideComputerName

 

Листинг 3. Группируем вывод по владельцу файла

$sb={
Param($path)
$data=dir $path |
where {-not $_.PSIsContainer} |
select name, @{Name=«Owner»;Expression=
{(Get-ACL $_.fullname).Owner}},length
$data | group -property owner |
Select @{Name=«Computername»;Expression={$env:computername}},
@{Name=«Path»;Expression={$path}},Name,Count,@{Name=
«Size»;Expression={
($_.Group | Measure-Object -Property Length -sum).Sum}}
} #sb
<#
Run the command remotely and suppress the RunspaceID since we
don't really need it.
#>
Invoke-Command -ScriptBlock $sb -ComputerName CHI-FP01
-ArgumentList@(«c:sharespublic») -HideComputerName |
Select * -ExcludePropertyRunspaceID

 

Листинг 4. Определяем возраст файла

PS C:work> get-item wishlist.txt | format-list name,
CreationTime,LastWriteTime,
>>@{Name=«Age»;Expression={(Get-Date)-$_.LastWriteTime}},
>>@{Name=«Days»;Expression={((Get-Date)
-$_.LastWriteTime).TotalDays}}
>>
Name: wishlist.txt
CreationTime: 11/23/2010 10:31:10 PM
LastWriteTime: 2/15/2011 7:36:34 AM
Age: 511.06:42:17.4251748
Days: 511.279372271039

 

 

Листинг 5. Определяем время последнего изменения файла

$path=«c:scripts»
#Get some other properties in case we want to further
#break down each bucket.
$files=dir $path -recurse |
Select Fullname,CreationTime,LastWriteTime,Length,
@{Name=«Age»;Expression={(Get-Date)-$_.LastWriteTime}},
@{Name=«Days»;Expression={[int]((Get-Date)
-$_.LastWriteTime).TotalDays}}
$hash=@{
Path=$path
Over= ($files | Where {$_.Days -gt 365} | Measure-Object).Count
'365Days'= ($files | Where {$_.Days -gt 180 -AND
$_.Days -le 365} | Measure-Object).Count
'180Days'= ($files | Where {$_.Days -gt 90 -AND
$_.Days -le 180} | Measure-Object).Count
'90Days'= ($files | Where {$_.Days -gt 30 -AND
$_.Days -le 90} | Measure-Object).Count
'30Days'= ($files | Where {$_.Days -gt 7 -AND
$_.Days -le 30} | Measure-Object).Count
'7Days'= ($files | Where {$_.Days -gt 0 -AND
$_.Days -le 7} | Measure-Object).Count
}
New-Object -TypeNamePSObject -Property $hash |
Select Path,Over,365Days,180Days,90Days,30Days,7Days

 

 

Листинг 6. Создание, изменение и применение правила доступа

$sb={
Param($path)
$du=new-object System.Security.AccessControl.FileSystem
AccessRule «jdhlabdomain users»,«Modify»,«allow»
$acl = Get-ACL $path
$acl.AddAccessRule($du)
Set-Acl -Path $path -AclObject $acl
}

 

Листинг 7. Настройка общего ресурса

PS C:> Set-SmbShare -Name Files -EncryptData $True
-FolderEnumerationModeAccessBased -CachingMode
Documents -CimSession SRV2K12RC
Confirm
Are you sure you want to perform this action?
SRV2K12RC: Performing operation 'Modify' on Target '*,Files'.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?]
Help (default is «Y"):

 

Листинг 8. Удаление общего ресурса

PS C:> Remove-SmbShare -Name Files -CimSession SRV2K12RC
Confirm
Are you sure you want to perform this action?
SRV2K12RC: Performing operation 'Remove-Share' on Target
'*,Files'.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?]
Help (default is»Y«):

 

 

Листинг 9. Создание общего ресурса и установка прав NTFS

Workflow New-FileShare {
Param(
[string]$Name,
[string]$Path,
[string]$Principal,
[string]$Right=»Modify«
)
#This must be done first.
Sequence {
#create the folder
Write-Verbose -Message»Creating new folder $path on
$pscomputername«
$newfolder = New-Item -Path $path -ItemType Directory
}
#Then this step can happen.
Sequence {
Parallel {
#these commands can happen in parallel
InlineScript {
Write-Verbose -Message»Modifying NTFS permissions«
Write-Verbose -Message»Creating entry for
$using:principal with a right of $using:Right«
$entry=New-Object -typenameSystem.Security
. AccessControl.FileSystemAccessRule -argumentlist
$using:Principal,$using:Right,»allow«
#get the existing ACL
$acl = Get-ACL -path $using:path
#add the new entry
$acl.AddAccessRule($entry)
Write-Verbose -Message»Applying the new ACL«
Set-Acl -Path $using:path -AclObject $acl
} #inline
#Create the share.
Write-Verbose -message»Creating the file share $name«
$newshare = New-SmbShare -Name $name -Path $path
-Description»File share for $principal«-EncryptData $True
-FolderEnumerationModeAccessBased -CachingMode
Documents -FullAccess»$env:userdomaindomain admins«
-ChangeAccess $Principal
} #Parallel
} #sequence
#Get results.
Sequence {
Parallel {
Write-Verbose -Message»Getting the new share«
Get-SmbShare -Name $name
Write-Verbose -Message»Getting the new share access"
Get-SmbShareAccess -Name $name
}
}