管道到LogParser

时间:2016-01-30 13:58:18

标签: powershell pipeline logparser

我正在处理一组脚本来管理我需要在gzip的非常糟糕的IIS日志上执行的一些日志记录任务。在处理它时,我遇到了管道问题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。似乎没有工作。我不知道为什么要花这么长时间才能回来。

任何人都可以帮忙吗?我应该这样做吗?

我的最终目标是使用一种简单的方法在一组已经gzip压缩并存储在netapp设备中的IIS日志上运行logparser查询。到目前为止,我的ungzipping部分与管道配合良好,只要我直接管道到LogParser,它就可以工作。我在另一个PowerShell函数中调用LogParser时遇到了问题。

1 个答案:

答案 0 :(得分:0)

虽然在管道上下文中自动变量$_表示当前对象是正确的,但在您的情况下,您需要一个不同的自动变量($input,如Mathias所建议的那样),因为你需要处理函数输入,即使它来自管道:

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