从vmware.log文件中的最后一行检索数据?

时间:2017-07-05 18:46:12

标签: powershell virtual-machine powercli vcenter

我目前有一个脚本可以检索vCenter中VM的数据存储区中.vmx的上次修改日期。我需要进行更改,而不是使用和显示vmware.log文件中的最后一个日期(与.vmx位于同一数据存储区中)

我不确定如何获取该行并将其转换为XX / XX / XXXX格式。在日志文件中,它显示为例如Dec 23 10。如果这是不可能的,不用担心。我只需要拉出日志文件中的最后一行并将其导出到.csv文件。以下是我目前的代码:

add-pssnapin VMware.VimAutomation.Core

# ---------- Only modify the fields in this area -------------
$vCenter = 'qlab-copsmgr'                  #name of the vCenter 
$dataCenter = 'Fly-away Kit'               #name of the DataCenter 
$outputFile = $vCenter + '-LastDateUsed.csv'             #desired output file name

# ---------- No modification is needed in the below code. Do not edit   -------------
$columnName = "Name,DataStore,Date Last Used" | Out-File .\$OutputFile -Encoding ascii
Connect-VIServer $vCenter -WarningAction SilentlyContinue
$vmList = Get-VM | where { $_.PowerState -eq “PoweredOff”} | select Name
$vmList = $vmList -replace 'Name : ', '' -replace '@{Name=', '' -replace '}', ''

ForEach ($VM in $vmList)
{
    # Get configuration and path to vmx file
    $VMconfig = Get-VM $VM | Get-View | select config
    $VMXpath = $VMconfig.config.files.VMpathName

    # Remove and/or replace unwanted strings
    $VMXpath = $VMXpath -replace '\[','' -replace '\] ','\' -replace '@{Filename=','/' -replace '}','' -replace '/','\'

    # List the vmx file in the datastore
    $VMXinfo = ls vmstores:\$VCenter@443\$DataCenter\$VMXpath | Where {$_.LastWriteTime} | select -first 1 | select FolderPath, LastWriteTime

    # Remove and/or replace unwanted strings
    $VMXinfo = $VMXinfo -replace 'DatastoreFullPath=', '' -replace '@{', '' -replace '}', '' -replace ';', ',' -replace 'LastWriteTime=', ''

    # Output vmx information to .csv file
    $output = $VM + ', ' + $VMXinfo
    $output
    echo $output >> $OutputFile
}

2 个答案:

答案 0 :(得分:1)

我还需要从vmware.log文件中提取最后一个事件,以便回溯没有vCenter事件历史记录的VM的断电时间。我查看了文件时间戳,但发现某些VM进程和可能的备份解决方案可能会使它们变得无用。

我尝试阅读该文件,但遇到了PSDrive类型不支持Get-Content的问题。因此,对于我的解决方案,无论好坏,我都会使用LucD的一个脚本 - “检索日志”和“#39;来自http://www.lucd.info/2011/02/27/virtual-machine-logging/的脚本,它提取VMs vmware.log文件并将其复制到本地存储。然后我修改它以将vmware.log文件复制到本地临时文件夹,在删除文件之前从文件中读取最后一行并将日志的最后一行作为PS对象返回。

请注意,这很慢,我确定我对LucD脚本的黑客并不优雅,但它确实有效,我希望能帮到某人。

注意:这会将时间值从日志转换为PS日期对象,方法是将文件中的字符串时间戳简单地传递给Get-Date。我已经读过这对于非美国日期格式化没有预期效果。对于美国以外的用户,您可能需要查看此内容,或者只是从日志中传递原始时间戳字符串而不是转换它。

#Examples:
#$lastEventTime = (Get-VM -Name "SomeVM" | Get-VMLogLastEvent).EventTime
#$lastEventTime = Get-VMLogLastEvent -VM "SomeVM" -Path "C:\alternatetemp\"

function Get-VMLogLastEvent{
    param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)][PSObject[]]$VM,
    [string]$Path=$env:TEMP
    )

    process{   
        $report = @()

        foreach($obj in $VM){
            if($obj.GetType().Name -eq "string"){
                $obj = Get-VM -Name $obj
            }
            $logpath = ($obj.ExtensionData.LayoutEx.File | ?{$_.Name -like "*/vmware.log"}).Name
            $dsName = $logPath.Split(']')[0].Trim('[')
            $vmPath = $logPath.Split(']')[1].Trim(' ')
            $ds = Get-Datastore -Name $dsName
            $drvName = "MyDS" + (Get-Random)
            $localLog = $Path + "\" + $obj.Name + ".vmware.log"
            New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null
            Copy-DatastoreItem -Item ($drvName + ":" + $vmPath) -Destination $localLog -Force:$true
            Remove-PSDrive -Name $drvName -Confirm:$false

            $lastEvent = Get-Content -Path $localLog -Tail 1
            Remove-Item -Path $localLog -Confirm:$false

            $row = "" | Select VM, EventType, Event, EventTime
            $row.VM = $obj.Name
            ($row.EventTime, $row.EventType, $row.Event) = $lastEvent.Split("|")
            $row.EventTime = $row.EventTime | Get-Date
            $report += $row
         }
         $report        
    }
} 

这应该涵盖你的要求,但是为了进一步说明为什么我需要细节,哪条线之间的阅读也可能对你有益,我会继续。

我继承了数百个传统虚拟机,这些虚拟机已经从各种过去的收购和资产剥离中移除,其中许多已在vCenter实例之间移动,从而丢失了所有事件日志详细信息。当我在一个数据中心开始清理工作时,我有超过60TB的断电虚拟机。根据这些遗留的性质,还没有关于谁拥有或了解这些旧虚拟机的详细信息。

为此,我又找到了我发现的另一个剧本,也来自LucD:https://communities.vmware.com/thread/540397

这将关闭所有已关闭电源的VM,尝试通过vCenter事件历史记录确定关闭电源的时间。我将其修改为回退到上面的Get-VMLogLastEvent函数,以便在事件日志详细信息不可用时获取VM的最终关闭时间。

错误捕获可以改进 - 这会在虚拟机上出错,因为某种原因导致没有vmware.log文件。但是快速而肮脏的我发现这个工作并提供了超过90%我需要的细节。

这再次依赖于上面的函数,对我来说,至少错误只是通过传递空值而失败。有人可能会在尝试复制之前添加对vmware.log存在的检查来删除错误,但由于数据存储的PSDrive接口速度较慢,这会在执行时增加触摸延迟。

$Report = @()  

$VMs = Get-VM | Where {$_.PowerState -eq "PoweredOff"}  
$Datastores = Get-Datastore | Select Name, Id  
$PowerOffEvents = Get-VIEvent -Entity $VMs -MaxSamples ([int]::MaxValue) | where {$_ -is [VMware.Vim.VmPoweredOffEvent]} | Group-Object -Property {$_.Vm.Name}  

foreach ($VM in $VMs) {  
    $lastPO = ($PowerOffEvents | Where { $_.Group[0].Vm.Vm -eq $VM.Id }).Group | Sort-Object -Property CreatedTime -Descending | Select -First 1 
    $lastLogTime = "";

    # If no event log detail, revert to vmware.log last entry which takes more time...
    if (($lastPO.PoweredOffTime -eq "") -or ($lastPO.PoweredOffTime -eq $null)){
        $lastLogTime = (Get-VMLogLastEvent -VM $VM).EventTime
    }

    $row = "" | select VMName,Powerstate,OS,Host,Cluster,Datastore,NumCPU,MemMb,DiskGb,PoweredOffTime,PoweredOffBy,LastLogTime
    $row.VMName = $vm.Name  
    $row.Powerstate = $vm.Powerstate  
    $row.OS = $vm.Guest.OSFullName  
    $row.Host = $vm.VMHost.name  
    $row.Cluster = $vm.VMHost.Parent.Name  
    $row.Datastore = $Datastores | Where{$_.Id -eq ($vm.DatastoreIdList | select -First 1)} | Select -ExpandProperty Name  
    $row.NumCPU = $vm.NumCPU  
    $row.MemMb = $vm.MemoryMB  
    $row.DiskGb = Get-HardDisk -VM $vm | Measure-Object -Property CapacityGB -Sum | select -ExpandProperty Sum  
    $row.PoweredOffTime = $lastPO.CreatedTime  
    $row.PoweredOffBy   = $lastPO.UserName
    $row.LastLogTime = $lastLogTime
    $report += $row  
}  

# Output to screen  
$report | Sort Cluster, Host, VMName | Select VMName, Cluster, Host, NumCPU, MemMb, @{N='DiskGb';E={[math]::Round($_.DiskGb,2)}}, PoweredOffTime, PoweredOffBy | ft -a  

# Output to CSV - change path/filename as appropriate  
$report | Sort Cluster, Host, VMName | Export-Csv -Path "output\Powered_Off_VMs_Report.csv" -NoTypeInformation -UseCulture  

干杯! 我祈祷这可以回报我曾经使用的一些业力。

Meyeaard

答案 1 :(得分:0)

我制作了一个逐行检查的脚本,如果找到了字符串,则将其更改为所需的格式

#example input you can use get-content PATH to txt or any file and assign it to $lines variable
$lines = @"
ernfoewnfnsf
ernfoewnfnsf
Dec 23 10 sgdsgdfgsdadasd
"@ -split "\r\n"

#checks line by line and if find anything that maches start of the line, one Big letter two small, space, two digits, space, two digits, space 
$lines | ForEach-Object{

    if ($_ -match "^[A-Z][a-z]{2}\s\d{2}\s\d{2}\s")
    {
        $match = [convert]::ToDateTime($matches[0])
        $_ -replace $matches[0], "$($match.ToShortDateString()) " | out-file { PATH } -APPEND
    }
    else
    {
        $_ | out-file { PATH } -APPEND
    }
}

只需使用filenamePAth更改{PATH},这应该适合您