2016-01-30 2 views
1

Я работаю над набором сценариев для управления некоторыми задачами ловушки, которые мне нужно выполнить на очень жестких журналах IIS, которые были gzipped. Во время работы над этим я столкнулся с проблемой с трубопроводом до logparser. Я упростил свою проблему следующим образом.Piping to LogParser

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

$query = "Select s-computername, Count(*) as count FROM stdin GROUP by s-computername" 
Get-Content .\01-01-16\ex160101.log | 
    LogParser "$query" -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON 

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

Вот что я получил.

Function Test-IISLog { 
    Begin { 
    $query = "Select s-computername, Count(*) as count FROM stdin GROUP by s-computername" 
    } 
    Process { 
    $_ | LogParser "$query" -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON | Write-Output 
    } 
} 
Get-Content .\01-01-16\ex160101.log | Test-IISLog 

Когда я запускаю это, он просто вращает его колеса в течение очень долгого времени. Я пробовал разные комбинации этой команды один без $_, а другой без Write-Output. Кажется, что никто не работает. Я не уверен, почему так долго нужно возвращаться.

Может ли кто-нибудь помочь в этом? Должен ли я делать это по-другому?

Моя конечная цель - простой способ запускать запрос logparser на набор журналов IIS, которые были gzipped и сохранены на устройстве netapp. До сих пор у меня была свободная порция, работающая хорошо с трубами, и до тех пор, пока я напрямую подключаюсь к LogParser, она работает. Когда я звоню LogParser из другой функции PowerShell, у меня возникают проблемы.

+1

Заменить '$ _' с' $ input' –

+0

$ ввода дал те же результаты, $ _ – markdemich

ответ

0

Хотя верно, что в контексте контура автоматическая переменная $_ представляет текущий объект, в вашем случае вам нужна другая автоматическая переменная ($input, как предложено Матиасом), поскольку вам необходимо обрабатывать ввод функции, хотя это происходит из трубопровода:

function Test-IISLog { 
    End { 
    $query = "SELECT s-computername, Count(*) AS count FROM stdin GROUP BY s-computername" 
    $input | LogParser "$query" -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON 
    } 
} 

Цитирование из documentation:

$Input
Содержит перечислитель, который перечисляет все входные данные, передаваемые функции. Переменная $input доступна только для функций и блоков сценариев (которые являются неназванными функциями). В блоке функции Process переменная $input перечисляет объект, который в настоящее время находится в конвейере. Когда блок Process завершается, в конвейере нет объектов, поэтому переменная $input перечисляет пустую коллекцию. Если функция не имеет блока Process, то в блоке End переменная $input перечисляет совокупность всех входных данных функции.

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

function Test-IISLog { 
    [CmdletBinding()] 
    Param(
    [Parameter(
     Mandatory=$true, 
     Position=0, 
     ValueFromPipeline=$true, 
     ValueFromPipelineByPropertyName=$true 
    )] 
    [string[]]$LogLine 
) 

    Begin { 
    $query = "SELECT s-computername, Count(*) AS count FROM stdin GROUP BY s-computername" 
    $lines = @() 
    } 
    Process { 
    $lines += $LogLine 
    } 
    End { 
    $lines | LogParser "$query" -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON 
    } 
} 

Однако зачем во всех этих проблемах в первую очередь?logparser может читать файлы сам по себе:

$filename = 'C:\path\to\ex160101.log' 

$query = @" 
SELECT s-computername, Count(*) AS count 
FROM '$filename' 
GROUP BY s-computername 
"@ 

& logparser.exe $query -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON 

Если что-то я бы передать имя файла в функции:

function Test-IISLog { 
    [CmdletBinding()] 
    Param(
    [Parameter(
     Mandatory=$true, 
     Position=0, 
     ValueFromPipeline=$true, 
     ValueFromPipelineByPropertyName=$true 
    )] 
    [ValidateScript({Test-Path -LiteralPath $_})] 
    [string]$Filename 
) 

    Process { 
    $query = @" 
SELECT s-computername, Count(*) AS count 
FROM '$filename' 
GROUP BY s-computername 
"@ 
    & logparser.exe $query -i:IISW3C -o:CSV -headers:ON -fileMode:1 -q:ON 
    } 
} 
+0

Я попробую ваш пример и дам вам знать, как это работает. Причина, по которой не имеет анализатор журнала, читает файл, потому что у моего варианта использования есть куча файлов, которые gzipped, которые мне нужно передать для анализатора парсера как одного. Мой пример выше - упрощенная версия, потому что, независимо от части gzipped, я не мог заставить эту часть работать. – markdemich

+0

Я попробовал оба примера. Один использует $ input, а другой - с помощью @LogLine. Оба дали аналогичные результаты при использовании $ _. – markdemich

+0

Моя ошибка. Вам нужно обработать '$ input' всего в блоке' End', иначе каждая строка журнала будет обрабатываться индивидуально различными процессами logparser. Что, конечно, было бы совершенно бессмысленно. –