Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Отслеживать создания файла (http://forum.oszone.net/showthread.php?t=337296)

alexfeel30 21-10-2018 12:28 2836823

Отслеживать создания файла
 
Доброго времени суток! Помогите сделать батник, нужно отслеживать создания файла Log.log с определенной периодичностью, когда файл создался отслеживать в нем появление слова successful также с периодичностью, при появлении successful выполнить код ниже.
Заранее всем откликнувшимся спасибо.

YuS_2 21-10-2018 18:38 2836867

не лучшая идея, использовать для этого cmd. Если на борту имеется powershell, то можно сделать без особых проблем...

alexfeel30 21-10-2018 20:36 2836884

Любой вариант подойдет.

YuS_2 22-10-2018 00:40 2836916

Цитата:

Цитата alexfeel30
нужно отслеживать создания файла 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)

Цитата:

Цитата alexfeel30
также с периодичностью, при появлении successful выполнить код ниже. »

А вот тут уже не совсем понятно... что же требуется?
Отслеживать только появление файла с однократным его чтением, на предмет наличия слова или же ещё требуется отслеживание изменения файла? В принципе и это возможно, вопрос только в том, как часто он будет обновляться. В том смысле, что его обновления надо обрабатывать, а вот как это делать - вопрос. При каждом обновлении искать совпадение или же с каким-либо периодом времени?

Iska 22-10-2018 00:44 2836917

Цитата:

Цитата YuS_2
А вот тут уже не совсем понятно... что же требуется? »

Коллега alexfeel30 сейчас выложит код на пакетных файлах, который нужно будет перевести на PowerShell.

YuS_2 22-10-2018 01:08 2836919

Цитата:

Цитата Iska
Коллега alexfeel30 сейчас выложит код на пакетных файлах »

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

megaloman 22-10-2018 11:15 2836955

Цитата:

Цитата Iska
Коллега alexfeel30 сейчас выложит код на пакетных файлах, который нужно будет перевести на PowerShell. »

А потом надо будет, чтобы окно выполнения не было видно. :)
Если интервал опроса кратен минуте, то лучше задание поставить в планировщик, пускай он задаёт интервал опроса, при этом код совсем простой (или я задачу не прочувствовал, в чём сложность CMD?)
Код:

@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

Busla 22-10-2018 12:42 2836969

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
      }
    }
  }
}

ему поплохеет, если вместо лога создать директорию с таким именем; ну и если лог уже есть, то отслеживать не будет

YuS_2 22-10-2018 13:50 2836975

Цитата:

Цитата megaloman
А потом надо будет, чтобы окно выполнения не было видно. »

дык, это вообще не проблема же. :)

Цитата:

Цитата Busla
зачем в PoSh все эти таймауты и задержки? - нужно просто подписаться на событие. »

Да, возможно. Это была готовая функция у меня, чуть модифицировал только... для чего создавалась, уже и не упомню.

Цитата:

Цитата Busla
И грузить в память весь файл тоже не надо. Это лог, который может достигать неслабых размеров. »

Согласен, можно и построчно парсить... а если файл достаточно большой, то можно и порциями строк... не принципиально.

А вообще, тут и велосипедов изобретать не надо, уже есть изобретенные до нас... :)
... вот тут есть чужой скриптик, опубликую со ссылкой на автора:
скрипт watchdog.ps1
Код:

<# 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/lib...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 2837038

Всем спасибо, взял код megaloman-а все работает как надо.


Время: 09:06.

Время: 09:06.
© OSzone.net 2001-