Показать полную графическую версию : [решено] Отслеживать создания файла
alexfeel30
21-10-2018, 12:28
Доброго времени суток! Помогите сделать батник, нужно отслеживать создания файла Log.log с определенной периодичностью, когда файл создался отслеживать в нем появление слова successful также с периодичностью, при появлении successful выполнить код ниже.
Заранее всем откликнувшимся спасибо.
не лучшая идея, использовать для этого cmd. Если на борту имеется powershell, то можно сделать без особых проблем...
alexfeel30
21-10-2018, 20:36
Любой вариант подойдет.
нужно отслеживать создания файла Log.log с определенной периодичностью, когда файл создался отслеживать в нем появление слова successful»
Вот готовая функция слежения за каталогом, на создание файла:
# Каталог, в котором будем следить за файлами
$pth = "c:\111\"
# Таймаут цикла ожидания (в мс.)
$tout = 1000
# Задержка чтения файла (в мс.)
$delay = 1000
# Объект следящий за появлением события:
$wtch = new-object system.io.filesystemwatcher
$wtch.path = $pth
# При необходимости задаём фильтр
$wtch.filter = "log.log"
do {
$res = $wtch.waitforchanged("created", $tout)
# Значение true, если время ожидания метода WaitForChanged истекло;
# в противном случае — значение false.
if ($res.timedout -eq $false){
sleep -m $delay
if ((gc ($pth+$res.name) -enc utf8 -raw) -match 'successful'){
"выполняемый код"
}
}
} until ([system.console]::keyavailable)
также с периодичностью, при появлении successful выполнить код ниже. »
А вот тут уже не совсем понятно... что же требуется?
Отслеживать только появление файла с однократным его чтением, на предмет наличия слова или же ещё требуется отслеживание изменения файла? В принципе и это возможно, вопрос только в том, как часто он будет обновляться. В том смысле, что его обновления надо обрабатывать, а вот как это делать - вопрос. При каждом обновлении искать совпадение или же с каким-либо периодом времени?
А вот тут уже не совсем понятно... что же требуется? »
Коллега alexfeel30 сейчас выложит код на пакетных файлах, который нужно будет перевести на PowerShell.
Коллега alexfeel30 сейчас выложит код на пакетных файлах »
ну, переводить необязательно... можно попытаться скрестить их :)
megaloman
22-10-2018, 11:15
Коллега alexfeel30 сейчас выложит код на пакетных файлах, который нужно будет перевести на PowerShell. »А потом надо будет, чтобы окно выполнения не было видно. :)
@Echo Off
Set "File=Z:\Box_In\Log.Log"
Set "Keyword=successful"
If Not Exist "%File%" Exit /B 2
Echo File Exist %File%
Find /I "%Keyword%" "%File%" >nul || Exit /B 1
Echo %Keyword% found
Exit /B 0
@Echo Off
Set "File=Z:\Box_In\Log.Log"
Set "Keyword=successful"
Set "TOutSec=5"
Set "TOutCom=Timeout /T %TOutSec% >nul"
:Begin
If Not Exist "%File%" (%TOutCom% &GoTo :Begin)
Find /I "%Keyword%" "%File%" >nul || (%TOutCom% &GoTo :Begin)
Echo %Date% %Time% %Keyword% found
%TOutCom% &GoTo :Begin
Exit /B 0
А вот если надо чтобы окно не было видно - тогда вперёд на vbs/js
YuS_2, зачем в PoSh все эти таймауты и задержки? - нужно просто подписаться на событие. И грузить в память весь файл тоже не надо. Это лог, который может достигать неслабых размеров.
Я бы примерно так сделал:
$watchedFile = 'C:\temp\abc.log'
$waitingWord = 'successful'
$watcher = New-Object System.IO.FileSystemWatcher(Split-Path -LiteralPath $watchedFile)
$subscription = Register-ObjectEvent -InputObject $watcher -EventName Created -Action {
if ($event.SourceEventArgs.Name -eq (Split-Path -Leaf $watchedFile)) {
Get-Content -Path $watchedFile -Wait | % {if ($_ -match $waitingWord) {
Write-Host "Обнаружено слово $waitingWord"
Unregister-Event -SubscriptionId $subscription.Id
break
}
}
}
}
ему поплохеет, если вместо лога создать директорию с таким именем; ну и если лог уже есть, то отслеживать не будет
А потом надо будет, чтобы окно выполнения не было видно. »
дык, это вообще не проблема же. :)
зачем в PoSh все эти таймауты и задержки? - нужно просто подписаться на событие. »
Да, возможно. Это была готовая функция у меня, чуть модифицировал только... для чего создавалась, уже и не упомню.
И грузить в память весь файл тоже не надо. Это лог, который может достигать неслабых размеров. »
Согласен, можно и построчно парсить... а если файл достаточно большой, то можно и порциями строк... не принципиально.
А вообще, тут и велосипедов изобретать не надо, уже есть изобретенные до нас... :)
... вот тут есть чужой скриптик, опубликую со ссылкой на автора:
<# Garry Geller
Набор функций-командлетов для наблюдения за изменениями файлов\директорий на основе
класса FileSystemWatcher. Для удобства использования можно поместить их в файл
powershell профиля - тогда они будут доступны наравне с прочими командами сразу из
консоли, либо поместить файл модуля watchdog.ps1 в папку powershell модулей.
#>
# required -version 3.0
set-alias swatch Set-Watch
function Set-Watch() {
<#
.SYNOPSIS
Запускает фоновый процесс отслеживания изменений файловой системы на основе класса FileSystemWatcher
.DESCRIPTION
Существующие фильтры отслеживаемых изменений:
NotifyFilters.CreationTime
NotifyFilters.LastAccess
NotifyFilters.LastWrite
NotifyFilters.FileName
NotifyFilters.DirectoryName
NotifyFilters.Security
NotifyFilters.Size
NotifyFilters.Attributes
.EXAMPLE
PS C:\> . .\watchdog.ps1
PS C:\> swatch -path "d:\test" -filter "*.txt" -event Created,Deleted
.EXAMPLE
PS C:\> swatch -path "d:\test" -filter "*.txt" -event Created,Deleted -command "start-process notepad.exe" -test
.LINK
https://msdn.microsoft.com/ru-ru/library/system.io.filesystemwatcher(v=vs.110).aspx
.LINK
Remove-Watch
.LINK
Disable-Watch
.LINK
Enable-Watch
.LINK
Get-Watch
#>
[CmdletBinding()]
param(
# путь до отслеживаемой директории
[parameter(Mandatory=$true,Position=1)]
[alias("p")][string]$path,
[parameter(Mandatory=$true,Position=2)]
# фильтр типов отслеживаемых файлов
[alias("f")][string]$filter="*.*",
# задает тип отслеживаемых изменений
[alias("n")][string]$notify='FileName, LastWrite',
# нужно ли рекурсивно отслеживать субдиректории
[alias("r")][switch]$recurse,
# событи(e|я) на котор(ое|ые) нужно реагировать
[parameter(Mandatory=$true,Position=3)]
[ValidateSet("Created","Deleted","Renamed","Changed")]
[alias("e")][string[]]$events,
[parameter(Mandatory=$false)]
# строковые идентифкаторы событий
[alias("name")][string[]]$id=@(),
# действие которое нужно выполнить - передается одной строкой вместе с аругментами
[string]$command,
# вывод переданных аргументов
[switch]$test
)
$fsw = New-Object IO.FileSystemWatcher -Property @{
Path = $path
Filter = $filter
IncludeSubdirectories = $recurse
NotifyFilter = [IO.NotifyFilters]$notify
}
Set-Variable __watcher -Value $fsw -Scope Script
Set-Variable command -Value $command -Scope Script
$action = {
#$command = Get-Variable command -valueOnly -Scope Global
$fullPath = $event.SourceEventArgs.FullPath
$fileName = $event.SourceEventArgs.Name
$changeType = $event.SourceEventArgs.ChangeType
$timeStamp = $event.TimeGenerated
Write-Host "The file '$fileName' was $changeType at $timeStamp"
if (![String]::IsNullOrEmpty($command)) {
Invoke-Expression $command
}
}
$calls = [Collections.ArrayList]::new()
for ($i=0; $i -lt $events.length; $i++) {
if ($id.Length -eq $events.Length){
$jobname = $id[$i]
} else {
$jobname = $events[$i]
}
$params = @{SourceIdentifier = $jobname; Action = $action}
if ((get-job).Name -ccontains $jobname) {
Write-Host "Задание $jobname уже существует" -f Red
} else {
$regEvent = Register-ObjectEvent $fsw $events[$i] @params
$calls.Add($regEvent)|Out-Null
}
}
# выводим аргументы функции
if ($test) {
$MyInvocation.BoundParameters.GetEnumerator() | Foreach {
echo "-$($_.Key): $($_.Value)"
}
$MyInvocation.UnboundArguments
'----------------------------'
}
return $calls
}
set-alias unwatch Disable-Watch
function Disable-Watch() {
<#
.SYNOPSIS
Временно отключает обработку событий
.LINK
Enable-Watch
.LINK
Remove-Watch
.LINK
Get-Watch
.LINK
Set-Watch
#>
if ($__watcher) {
$__watcher.EnableRaisingEvents = $false
Write-Host "Отслеживание событий отключено" -f Yellow -b DarkGray
}
}
set-alias watch Enable-Watch
function Enable-Watch() {
<#
.SYNOPSIS
Включает обработку событий
.LINK
Disable-Watch
.LINK
Remove-Watch
.LINK
Get-Watch
.LINK
Set-Watch
#>
if ($__watcher) {
$__watcher.EnableRaisingEvents = $true
Write-Host "Отслеживание событий включено" -f Green -b DarkGray
}
}
set-alias gwatch Get-Watch
function Get-Watch() {
<#
.SYNOPSIS
Получает сторожевой объект для установки новых свойств (если указаны)
и возвращает его
.EXAMPLE
PS C:\> (gwatch).filter = "*.*" # установить новый файловый фильтр
PS C:\> gwatch -Filter *.*
.EXAMPLE
PS C:\> (gwatch).path= "c:\windows" # установить новую директорию для отслеживания
PS C:\> gwatch -Path "c:\windows"
.EXAMPLE
PS C:\> gwatch -NotifyFilter "Filename,LastWrite,LastAccess" -Filter "*.*"
.EXAMPLE
PS C:\> gwatch -IncludeSubdirectories
PS C:\> gwatch -IncludeSubdirectories:$false
.OUTPUTS
FileSystemWatcher
.LINK
Set-Watch
.LINK
Disable-Watch
.LINK
Remove-Watch
.LINK
Get-Watch
#>
param(
[string]$Path,
[string]$Filter,
[switch][Boolean]$IncludeSubdirectories,
[string]$NotifyFilter
)
if ($__watcher -eq $null) {
Write-Host "Объект FileSystemWatcher не определен" -f Red
} else {
$type_watcher = $__watcher.gettype()
$MyInvocation.BoundParameters.GetEnumerator() | %{
$key = $_.Key
$value = $_.Value
if ($key -eq "NotifyFilter") {
$value = [IO.NotifyFilters]$value
}
if ($key -eq "IncludeSubdirectories") {
[Boolean]$value = $value
}
$prop = $type_watcher.GetProperty($key)
$prop.SetValue($__watcher, $value)
}
return $__watcher
}
}
set-alias rwatch Remove-Watch
function Remove-Watch() {
<#
.SYNOPSIS
Удаляет задание по списку имен, либо все
.EXAMPLE
PS C:\> rwatch Created,Deleted # удалить задания по именам
.EXAMPLE
PS C:\> rwatch # удалить все задания
.LINK
Set-Watch
#>
[CmdletBinding()]
param(
[string[]]$names
)
if ($names.Length -eq 0) {
$names = (get-job).Name
}
foreach ($jobname in $names) {
if ((get-job).Name -ccontains $jobname) {
Unregister-Event $jobname -Force
Remove-Job -Name $jobname -Force
Write-Host "Задание $jobname удалено" -f Green -b DarkGray
} else {
Write-Host "Задание $jobname не найдено" -f Yellow -b DarkMagenta
}
}
Set-Variable __watcher -Value $null -Scope Script
}
Полностью управляемый, подписывается на событие создания, изменения, удаления файлов, с возможностью ввода команд для исполнения. В общем, достаточно универсальный... удовлетворит любую потребность
alexfeel30
22-10-2018, 20:21
Всем спасибо, взял код megaloman-а все работает как надо.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.