我目前有一个脚本可以检索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
}
答案 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},这应该适合您