使用标头导入CSV,扫描远程服务器上的日志,将数据添加到阵列,将阵列导出为CSV

时间:2016-11-30 05:37:55

标签: arrays powershell csv

我需要使用我已经使用了大约一年的模板回到绘图板,该模板从带有标题的.csv中读取值,打开哈希表数组,更新服务器上的各种属性作为扫描运行(ping,日志,服务等),最后导出到.csv或gridview。

基于哈希表的阵列模板在过去的各种功能中运行良好,但是我发现它在尝试对多个服务器进行大规模GCI扫描时不起作用。所以今晚,我尝试使用常规@()数组重新编写。但是,有两个问题:

  • 输入CSV上的标题是"服务器"和"平台",但它们没有反映在输出中。而是显示第一个条目的列标题。
  • if (GCI ...)代码无效,我不确定原因。

以下是代码:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$ShortDate = (Get-Date).ToString('MM/dd/yyyy')
$InputCSV = @(Import-csv $Dir\Masters.csv)

function PingEM {
    Param($_)
    $Error.Clear()
    try {
        $Ping = New-Object System.Net.NetworkInformation.Ping
        $PingReturn = $Ping.Send($_, 1000) | select Status -ExpandProperty Status
    } catch {}

    if (($Error) -or ($PingReturn -ne "Success")) {
        Write-Host "$_ is offline. Remaining checks will be skipped" -ForegroundColor Red
        $Ping = "Offline"
        $TaskSeq = "N/A"
        $Completed = "N/A"
    } else {
        Write-Host "Online" -ForegroundColor Green
        $Ping = "Online"
    }
}

$OutArray = @()

foreach ($Item in $InputCSV) {
    $outarray += New-Object PSObject -Property @{
        Server = $Item.Server
        Platform = $Item.Platform        
    }

    PingEM $($Item.Server)

    if ($Ping -eq "Online") {
        Write-Host "Checking $($Item.Server) now"

        if (GCI \\$($Item.Server)\c$\log\Results_*.html -EA 0 | Where { $_.LastWriteTime -ge "$ShortDate" }) {
            Write-Host "Recent log found!"
        } else {
            Write-Host "Recent log NOT found!"
        }
    }
} # PING

$OutArray

2 个答案:

答案 0 :(得分:1)

以下代码应该有效。你有$.LastWriteTime的拼写错误,你需要使用$_.LastWriteTime。您还尝试定义$Server$Platform的变量,而不是将其指定为哈希表中的属性。最后,修改了GCI命令以引用$($Item.Server)而不是$Server的未定义变量。

代码:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$ShortDate = (Get-Date).ToString('MM/dd/yyyy')
$InputCSV = @(Import-csv $Dir\Servers.csv)

$OutArray = @()

ForEach ($Item in $InputCSV) 
{
    if (GCI \\$($Item.Server)\c$\*.log -EA 0 | Where { $_.LastWriteTime -ge "$ShortDate" })
    {
        $Completed = "Yes"
    }else{
        $Completed = "No"
    }

    $outarray += New-Object PsObject -property @{
    Server = $Item.Server
    Platform = $Item.Platform
    Completed = $Completed
    }

} 
$OutArray

答案 1 :(得分:0)

您的代码存在以下问题:

  • $_automatic variable。请勿将其用作Param()
  • 您在$Ping的{​​{3}}中创建并初始化PingEM()$Ping条件中的if是一个不同的变量(在不同的范围内),因此它是空的。
  • 您在$Ping内使用变量PingEM()来表示不同的事物(Ping对象以及状态字符串)。不要重复使用变量。
  • 让您的功能实际返回状态(或状态对象)。 PowerShell在local scope上运行return所有未捕获的输出,因此只需回显" Online"或"离线"就够了。
  • 使用像Success output stream这样的cmdlet通常比使用System.Net.NetworkInformation.Ping等.Net类更多PoSh。在某些情况下,由于性能原因,.Net类更受欢迎,但大多数情况下cmdlet更简单,更易于使用。

将您的功能更改为:

function PingEM {
    Param($server)

    if (Test-Connection $server -Count 1 -TimeToLive 1 -Quiet) {
        Write-Host "Online" -ForegroundColor Green
        'Online'
    } else {
        Write-Host "$_ is offline. Remaining checks will be skipped" -ForegroundColor Red
        'Offline'
    }
}

所以你可以像这样使用它:

if ((PingEM $Item.Server) -eq 'Online') {
  ...
}

请注意,您需要将函数调用放在括号中,否则PowerShell会将-eq解释为函数的参数而不是相等比较运算符。如果在字符串中使用它,则只需要$Item.Server周围的子表达式。