1

我正在处理一些将采用一系列性能计数器的代码,然后将计数器放在一个 .csv 文件中,该文件每次达到 1MB 时都会翻转。

$Folder="C:\Perflogs\BBCRMLogs" # Change the bit in the quotation marks to whatever directory you want the log file stored in

$Computer = $env:COMPUTERNAME
$1GBInBytes = 1GB
$p = LOTS OF COUNTERS;

# If you want to change the performance counters, change the above list. However, these are the recommended counters for a client machine. 

$num  = 0
$file = "$Folder\SQL_log_${num}.csv"

if( !(test-path $folder)) {New-Item $Folder -type directory}

Get-Counter -counter $p -SampleInterval 2 -Continuous | Foreach {

    if ((Get-Item $file -ErrorAction SilentlyContinue ).Length -gt 1mb) 
    {
        $num +=1
        $file = "$Folder\SQL_log_${num}.csv"
    }

    $_

} | Foreach-Object { $_ | Export-Csv $file -Force -Append}

现在,它运作良好。迭代工作正常,每次 .csv 达到 1MB 时都会创建一个新文件。但是,第一个 .CSV 之后的每个 .CSV 在 2 分钟后已创建为 1MB,从而导致创建一个新文件。我不太确定为什么会发生这种情况,尽管我相信这是因为 Powershell 只是在每次创建它时重写整个 .csv。

4

2 回答 2

1

将最后一行更改为此,将每一行转换为 CSV 格式,然后将其附加到输出文件:

} | Foreach-Object {($_ | ConvertTo-Csv -NoTypeInformation)[1] | Out-File $file -Append -Encoding ASCII}.

几点注意事项:

  • -Encoding ASCII不是绝对必要的,但您可能在某些应用程序中遇到 Unicode CSV 文件的问题(例如,Excel 默认不会将其作为 CSV 文件打开,所有内容都将在 A 列中)
  • index in 的原因($_ | ConvertTo-Csv -NoTypeInformation)[1]ConvertTo-Csv -NoTypeInformation每次还是输出标题行,所以要抓取双行输出的第二行(($_ | ConvertTo-Csv -NoTypeInformation)[0]就是标题行)
  • 由于您没有输出标题行,因此您需要在循环之前将一个输出到 $file
于 2013-06-04T21:22:29.857 回答
1

[我将其发布为新答案,而不是编辑原始答案,因为它完全不同。替换或附加到原始答案会使随后的讨论变得混乱。]

您需要做的是使用正则表达式从 Get-Counter 输出的 Readings 属性中提取值,并从时间戳和这些值手动构造 CSV 输出。将最后一行更改为此(根据您的首选样式设置格式):

| %{'"' + (Get-Date $_.Timestamp -f 's') + '","' + (([regex]::matches($_.Readings, '(?<=\\\\.+?:\n)(.+?)(?=\n)') | select -ExpandProperty Value) -join '","') + '"'} | Out-File $file -Append -Encoding ASCII

打破它:

  • (Get-Date $_.Timestamp -f 's') 这部分不是绝对必要的,尽管我认为它会让你的结果更容易理解。's' 格式将日期置于 ISO 8601 可排序模式中。您可以将“u”替换为另一种可排序格式,或使用您最喜欢的自定义格式字符串。或者只是将其替换为$_.Timestamp以保留原始格式。
  • [regex]::matches($_.Readings, '(?<=\\\\.+?:\n)(.+?)(?=\n)')正则表达式匹配任何以\\开头并以:结尾 的行的内容(您想摆脱的那些讨厌的计数器名称)。请注意,我使用的是[regex]::matches,它执行全局匹配,而不是[regex]::match-match,它只会为您提供每个字符串的第一个匹配项(读数属性是单个字符串,因此只会返回第一个计数器读数)。
  • | select -ExpandProperty Value 生成一个包含所有匹配项的数组,然后您可以将其加入","并用"包围以生成 CSV 输出。

由于您没有使用转换函数,因此您还需要构造一个标题行。在管道正上方添加此行:

`'"Timestamp","' + ($p -join '","') + '"' | Out-File $file -Append -Encoding ASCII`

这是假设 $p 是一个数组(它应该是)。如果它是一个字符串,那么根据格式,您可以按原样使用它,或者 -拆分它并以 CSV 格式重新加入它。

于 2013-06-07T23:46:53.643 回答