Отслеживание изменений файлов в папке с помощью PowerShell

В сценариях, когда вам нужно отслеживать изменения в определенной папке и выполнять какое-то автоматические действие при обнаружении изменений в файле/директории (отправить уведомление, логировать событие в текстовый файл или журнал событий, запускать скрипт обработки и т.д.) вместо использования классического аудита событий доступа к папкам в Windows, можно использовать встроенный .Net класс FileSystemWatcher. Этот класс позволяет в реальном времени отслеживать события создания, удаления, переименования и редактирования файлов (и папок). В статье мы рассмотрим, как следить за изменениями объектов файловой системы в определенной директории через FileSystemWatcher из PowerShell.

Создадим объект класса FileSystemWatcher:

$watcher = New-Object System.IO.FileSystemWatcher

Хотите ли вы отслеживать события во вложенных директориях:

$watcher.IncludeSubdirectories = $true

Указать целевую директорию, которой будете мониторить:

$watcher.Path = "C:\Configs"

Включить генерацию событий при обнаружении изменений:

$watcher.EnableRaisingEvents = $true

Настраиваем действие, которое нужно выполнить, если обнаружены изменения в отслеживаемой директории.

$action = {
$changeType = $Event.SourceEventArgs.ChangeType
$path = $Event.SourceEventArgs.FullPath
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | $changeType | $path" | Out-File -FilePath "C:\logs\watch.log" -Append
}

Осталось подписаться на определенные типы событий, которые вы хотите отслеживать. Всего доступно четыре типа событий Created, Changed, Deleted, Renamed. Я хочу отслеживать все эти типы событий, поэтому зарегистрирую все четыре подписки:

Register-ObjectEvent $watcher Created -Action $action -SourceIdentifier FSCreate
Register-ObjectEvent $watcher Changed -Action $action -SourceIdentifier FSChange
Register-ObjectEvent $watcher Deleted -Action $action -SourceIdentifier FSDelete
Register-ObjectEvent $watcher Renamed -Action $action -SourceIdentifier FSRename

PowerShell скрипт для отслеживания изменения файлов в папке

Мониторинг изменений в директории будет работать до тех пор, пока жив родительский процесс powershell.exe. Ядро Windows само отслеживает изменения в файловой системе и отправляет уведомления в ваши подписки. Cкрипт запускается один раз, поэтому не нужно добавлять в него циклы опроса. Но при запуске кода через PS1 скрипт, можно добавить в конец бесконечный цикл:

while ($true) {sleep 5}

Если скрипт PowerShell скрипт мониторинга папки запускается через планировщик задач или в виде отдельной службы Windows (создать службу из скрипта PowerShell можно с помощью NSSM).

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

Get-Content -Path "C:\logs\watch.log" -wait

Лог изменения в файлах

Чтобы остановить мониторинг, выполните:

Unregister-Event -SourceIdentifier FSCreate
Unregister-Event -SourceIdentifier FSChange
Unregister-Event -SourceIdentifier FSDelete
Unregister-Event -SourceIdentifier FSRename

Если нужно отслеживать изменения только в определенных типах файлах, в начале скрипта можно определить фильтр:

$filter = "*.cfg"
$watcher.Filter = $filter

Чтобы FileSystemWatcher реагировал только на определенные события, можно использовать NotifyFilter. Например, я хочу реагировать только если изменены NTFS права доступа, размер или имя файла:

$watcher.NotifyFilter = [System.IO.NotifyFilters]::FileName -bor [System.IO.NotifyFilters]::Size -bor [System.IO.NotifyFilters]::Security

Если нужно для определенного события сделать отдельный обработчик (действие), его можно указать сразу при подписке через параметр Action. В этом примере я хочу при переименовании файла, записывать в лог старое и новое имя файла.

Register-ObjectEvent $watcher Renamed -SourceIdentifier FSRename -Action {
$details = $Event.SourceEventArgs
$timeStamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$logMessage = "$timeStamp | Renamed | From: $($details.OldFullPath) To: $($details.FullPath)"
$logMessage | Out-File -FilePath "C:\logs\watch.log" -Append
}

При большом количестве событий (десятки/сотни в секунду), чтобы не терять события, можно увеличить размер внутреннего буфера до 64 кб:

$watcher.InternalBufferSize = 65536

или запускать каждой действие через отдельный фоновый процесс, добавив в Action вызов кода обработчика через Start-Job

Итак, мы рассмотрели, как с помощью PowerShell реализовать простую систему отслеживания изменения, создания, удаления и переименования файлов в указанной папке и автоматической реакции на события.


Предыдущая статья Следующая статья


Комментариев: 0 Оставить комментарий

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Я не робот( Обязательно отметьте)