Создание файлового архива средствами PowerShell

A. Vasiliev делится решением проблемы по архивированию старых данных.
Все, наверное, знакомы с проблемой разрастающейся файлопомойки документации на файл сервере. У нас она выросла почти уже до 2 Тб. Чистка данного ресурса весьма затруднительна: отделы держатся за свои файлы как за самое святое, и их можно понять. Иногда приходится обращаться к файлам двух-трех годичной давности.

Однако держать такой объем информации – непозволительная роскошь хотя бы с точки зрения времени выполнения бэкапа и его восстановления.

Отсюда появилась задачка: создать файловый архив старых документов, обеспечить в него доступ только на чтение, обеспечить прозрачный доступ для пользователей.

Реализация, как всегда, моя любимая – скрипт на powershell.

Суть реализации – мы переносим файлы, которые давно не изменялись на другое хранилище (возможно более медленное и дешевое), а на месте удаленных файлов создаем ярлыки на новое местоположение. Для пользователя получается абсолютно прозрачный доступ. Он часто даже не видит разницы – ярлык называется также как и файл, значок такой же, открывается также по двойному клику. Т.к. файлы переносим с сохранением NTFS прав, доступ остается неизменным.

Сам скрипт выглядит следующим образом:

param (
$src, # источник
$dst, # место хранения архива
$daysold = 2*365, # насколько старые файлы переносить
$logfile = "log.txt"
)

$src = $src.TrimEnd(“\”)
$dst = $dst.TrimEnd(“\”)
echo “Starting at $(get-date)” > $logfile
# копируем иерархию каталогов с правами
#xcopy $src $dst /t /e /o /c /h /y
robocopy $src $dst /E /SEC /XF *.* /NDL
echo “Directory hierarchy copied” >> $logfile
$curdate = get-date
$Shell = new-Object -com Wscript.Shell
# по всем файлам, которые изменены ранее $daysold дней назад
$files = dir $src -recurse | where { ($_.Attributes -ne “Directory”) -and ($_.Extension -ne “.lnk”) -and (($curdate – $_.LastWriteTime).TotalDays -ge $daysold) }
$files | % {
write-progress -activity “Processing” -status $_.FullName
$file = $_
# будущее местоположение файла на архиве
$targetfilename = ($file.FullName -replace $src.Replace(“\”,”\\”),$dst)
# если файл еще не существует в архиве
if ( -not (test-path $targetfilename) ) {
# перемещаем файл
move $file.FullName $targetfilename
echo “Moved $($file.FullName) To $targetfilename” >> $logfile
# создаем на него ярлык
$link = $Shell.CreateShortcut(“$($file.FullName).lnk”)
$link.TargetPath = $targetfilename
$link.Save()
echo “Link $($link.FullName) created” >> $logfile
# выставляем права на ярлык (добавляем запрет на изменение и удаление)
$acl = Get-Acl $link.FullName
$addacl = New-Object System.Security.AccessControl.FileSystemAccessRule(“Everyone”, “Delete,Write”, “Deny”)
$acl.AddAccessRule($addacl)
Set-Acl $link.FullName $acl
echo “Link $($link.FullName) denied” >> $logfile
}
else {
echo “File $($file.FullName) already exist in archive” >> $logfile
}
}

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

Leave a Reply

Your email address will not be published. Required fields are marked *