0

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

我不确定如何获取该行并将其转换为 XX/XX/XXXX 格式。例如,在日志文件中,它显示为 2010 年 12 月 23 日。如果这是不可能的,不用担心。我只需要提取日志文件中的最后一行并将其导出到 .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
}
4

2 回答 2

1

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

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

请注意,这很慢,我确信我对 LucD 脚本的破解并不优雅,但它确实有效,我希望能对某人有所帮助。

注意:这通过简单地将字符串时间戳从文件传送到 Get-Date 将时间值从日志转换为 PS 日期对象。我已经读到这对于非美国日期格式无法正常工作。对于美国以外的人,您可能想要查看此内容,或者只是从日志中传递原始时间戳字符串而不是对其进行转换。

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

这应该涵盖您的要求,但为了进一步说明为什么我需要详细信息,字里行间的阅读也可能使您受益,我将继续。

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

为此,我破解了我发现的另一个脚本,同样来自 LucD:https ://communities.vmware.com/thread/540397 。

这将包含所有关闭的虚拟机,尝试通过 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  

干杯! 我祈祷这可以偿还我使用的一些业力。

迈亚德

于 2018-02-26T16:00:14.277 回答
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} ,这应该适合你

于 2017-07-06T06:48:29.770 回答