在Powershell中创建日志文件

在Powershell中创建日志文件,powershell,Powershell,我有下面的代码,目前它加载屏幕上的所有信息。我希望它记录到D:\Apps\Logs上的日志文件中 日志文件需要有它所加载的计算机的名称-so COMPUTERNAME.log 你知道我该怎么做吗 谢谢 $computer = gc env:computername $onetcp = ((get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductMajorPart).tostring() $twotcp =

我有下面的代码,目前它加载屏幕上的所有信息。我希望它记录到D:\Apps\Logs上的日志文件中

日志文件需要有它所加载的计算机的名称-so COMPUTERNAME.log

你知道我该怎么做吗

谢谢

$computer = gc env:computername

$onetcp = ((get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductMajorPart).tostring() $twotcp = ((get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductMinorPart).tostring() $threetcp = ((get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductBuildPart).tostring() $fourtcp = ((get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductPrivatePart).tostring()


$onedfsr = ((get-childitem c:\windows\system32\dfsrs.exe).Versioninfo.ProductMajorPart).tostring() $twodfsr = ((get-childitem c:\windows\system32\dfsrs.exe).Versioninfo.ProductMinorPart).tostring() $threedfsr = ((get-childitem c:\windows\system32\dfsrs.exe).Versioninfo.ProductBuildPart).tostring() $fourdfsr = ((get-childitem c:\windows\system32\dfsrs.exe).Versioninfo.ProductPrivatePart).tostring()

write-host TCPIP.sys Version on $computer is: "$onetcp.$twotcp.$threetcp.$fourtcp" Write-Host write-host DFSRS.exe Version on $computer is: "$onedfsr.$twodfsr.$threedfsr.$fourdfsr"

Write-Host

If (get-wmiobject win32_share | where-object {$_.Name -eq "REMINST"}) {   Write-Host "The REMINST share exists on $computer" } Else {   Write-Host "The REMINST share DOES NOT exist on $computer - Please create as per standards"  }   Write-Host

$hotfix1 = Get-HotFix -Id KB2450944 -ErrorAction SilentlyContinue $hotfix2 = Get-HotFix -Id KB2582284 -ErrorAction SilentlyContinue $hotfix3 = Get-HotFix -Id KB979808 -ErrorAction SilentlyContinue

If ($hotfix1) {     Write-Host "Hotfix KB2450944 is installed"
-BackgroundColor Green -ForegroundColor Black   } else {    Write-Host "Hotfix KB2450944 is NOT installed - Please ensure you install this hotfix" -ForegroundColor "red"   }


If ($hotfix2) {     Write-Host "Hotfix KB2582284 is installed"
-BackgroundColor Green -ForegroundColor Black   } else {    Write-Host "Hotfix KB2582284 is NOT installed - Please ensure you install this hotfix" -ForegroundColor "red"   }

If ($hotfix3) {     Write-Host "Hotfix KB979808 is installed"
-BackgroundColor Green -ForegroundColor Black   } else {    Write-Host "Hotfix KB979808 is NOT installed - Please ensure you install this hotfix" -ForegroundColor "red"    }

将此项放在文件的顶部:

$Logfile = "D:\Apps\Logs\$(gc env:computername).log"

Function LogWrite
{
   Param ([string]$logstring)

   Add-content $Logfile -value $logstring
}

然后将
Write主机
调用替换为
LogWrite

函数,该函数将这些原则更进一步

  • Add的时间戳-不能有没有时间戳的日志
  • 添加级别(默认情况下使用信息)意味着您可以突出显示重大问题
  • 允许可选的控制台输出。如果不设置日志目的地,它只会将其输出

    Function Write-Log {
        [CmdletBinding()]
        Param(
        [Parameter(Mandatory=$False)]
        [ValidateSet("INFO","WARN","ERROR","FATAL","DEBUG")]
        [String]
        $Level = "INFO",
    
        [Parameter(Mandatory=$True)]
        [string]
        $Message,
    
        [Parameter(Mandatory=$False)]
        [string]
        $logfile
        )
    
        $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
        $Line = "$Stamp $Level $Message"
        If($logfile) {
            Add-Content $logfile -Value $Line
        }
        Else {
            Write-Output $Line
        }
    }
    
  • 日志旋转的要点:

    用法:

    . .\logger.ps1
    Write-Log "debug message"
    Write-Log "info message" "INFO"
    
    用这个

    脚本:

    Function Main {
        Log -File "D:\Apps\Logs\$Env:computername.log"
    
        $tcp = (get-childitem c:\windows\system32\drivers\tcpip.sys).Versioninfo.ProductVersionRaw
        $dfs = (get-childitem C:\Windows\Microsoft.NET\Framework\v2.0.50727\dfsvc.exe).Versioninfo.ProductVersionRaw
    
        Log "TCPIP.sys Version on $computer is:" $tcp
        Log "DFSVC.exe Version on $computer is:" $dfs
    
        If (get-wmiobject win32_share | where-object {$_.Name -eq "REMINST"}) {Log "The REMINST share exists on $computer"}
        Else {Log "The REMINST share DOES NOT exist on $computer - Please create as per standards"}
    
        "KB2450944", "KB3150513", "KB3176935" | ForEach {
            $hotfix = Get-HotFix -Id $_ -ErrorAction SilentlyContinue
            If ($hotfix) {Log -Color Green Hotfix $_ is installed}
            Else {Log -Color Red Hotfix $_ " is NOT installed - Please ensure you install this hotfix"}
        }
    }
    
    屏幕输出:

    日志文件(位于
    D:\Apps\Logs\.Log
    ):

    2017-05-31写入日志(版本:01.00.02,PowerShell版本:5.1.14393.1198)
    19:19:29.00 C:\Users\User\PowerShell\Write Log\Check.ps1
    19:19:29.47 is上的TCPIP.sys版本:{Major:10,Minor:0,Build:14393,Revision:1066,MajorRevision:0,MinorRevision:1066}
    19:19:29.50 is上的DFSVC.exe版本:{Major:2,Minor:0,内部版本:50727,修订版:8745,MajorRevision:0,MinorRevision:8745}
    19:19:29.60上不存在REMINST共享-请按照标准创建
    在25,13处出错:在“localhost”计算机上找不到请求的修补程序。验证输入并再次运行该命令。
    19:19:33.41未安装修补程序KB2450944-请确保安装此修补程序
    19:19:37.03已安装修补程序KB3150513
    19:19:40.77已安装修补程序KB3176935
    19:19:40.77完
    
    我已经使用这段代码有一段时间了,我有一些东西对我很有用。日志文件以前导“0”编号,但保留其文件扩展名。我知道每个人都喜欢为任何东西创建函数,但我开始删除执行一个简单任务的函数。当很少有人耍花招时,为什么要用很多词呢?可能会删除其他函数,并可能从其他块中创建函数。我将日志记录程序脚本保存在一个中心共享中,如果它已更改,则制作一个本地副本,或者如果需要,从中心位置加载它

    首先,我导入记录器:

    #Change directory to the script root
    cd $PSScriptRoot
    
    #Make a local copy if changed then Import logger
    if(test-path "D:\Scripts\logger.ps1"){
        if (Test-Path "\\<server>\share\DCS\Scripts\logger.ps1") {
            if((Get-FileHash "\\<server>\share\DCS\Scripts\logger.ps1").Hash -ne (Get-FileHash "D:\Scripts\logger.ps1").Hash){
                rename-Item -path "..\logger.ps1" -newname "logger$(Get-Date -format 'yyyyMMdd-HH.mm.ss').ps1" -force
                Copy-Item "\\<server>\share\DCS\Scripts\logger.ps1" -destination "..\" -Force 
            }
        }
    }else{
        Copy-Item "\\<server>\share\DCS\Scripts\logger.ps1" -destination "..\" -Force
    }
    . "..\logger.ps1"
    
    我记录的内容取决于我创建的调试级别:

    if ($Debug -ge 1){
        $message = "<$pid>Debug:$Debug`-Adding tag `"MetricClass:temp`" to $host_name`:$metric_name"
        Write-Log $message $logfile "DEBUG"
    }
    

    我相信这是将屏幕上的所有内容放入文件的最简单方法。它是一个本机PS CmdLet,因此您不必更改yout脚本中的任何内容

    Start-Transcript -Path Computer.log
    
    Write-Host "everything will end up in Computer.log"
    
    Stop-Transcript
    

    您可能只想使用新的TUN.Logging PowerShell模块,这也可以发送日志邮件。只需使用Start-Log和/或Start-MailLog cmdlet来启动日志记录,然后只需使用Write-HostLog、Write-WarningLog、Write-VerboseLog、Write-ErrorLog等来写入控制台和日志文件/邮件。然后在结束时调用Send Log和/或Stop Log,瞧,您得到了日志。 只需通过从PowerShell Gallery安装即可

    安装模块-名称TUN.Logging
    
    或者只需点击以下链接:


    该模块的文档可以在这里找到:

    对于对象的属性,您需要在前面用$将整个内容封装在括号中。尝试将其更改为:
    $(TCPIP.sys)
    要每次重新生成日志文件,您需要在顶部添加另一个部分来删除/创建文件(如果存在)。只需注意,您可以使用$env变量将计算机名嵌入字符串中,而无需使用
    get content
    和变量赋值
    Write Host“我的本地计算机名是:$env:computername”
    我还喜欢使用-passthrough标志,以便日志记录也输出到shell窗口。我建议根据已知谓词的命名约定命名函数:Write LogLog:术语“Log”不被识别为cmdlet、脚本文件的名称,或可操作程序。检查包含的名称的拼写,验证路径是否正确,然后重试。你也有日志功能吗?这应该是公认的答案。它是本地的,非常简单,易于使用。我建议添加
    -Append
    NoClobber
    ,否则会覆盖日志。还要注意的是,它作为一个标题输出了许多关于进程和主机的内容,因此它并不直接等同于屏幕上的内容,除非您使用
    -useMimimumHeader
    等参数。
    # all logging settins are here on top
    param(
        [Parameter(Mandatory=$false)]
            [string]$logFile = "$(gc env:computername).log",
        [Parameter(Mandatory=$false)]
            [string]$logLevel = "DEBUG", # ("DEBUG","INFO","WARN","ERROR","FATAL")
        [Parameter(Mandatory=$false)]
            [int64]$logSize = 10mb,
        [Parameter(Mandatory=$false)]
            [int]$logCount = 25
    ) 
    # end of settings
    
    function Write-Log-Line ($line, $logFile) {
        $logFile | %{ 
               If (Test-Path -Path $_) { Get-Item $_ } 
               Else { New-Item -Path $_ -Force } 
        } | Add-Content -Value $Line -erroraction SilentlyCOntinue
    }
    
    function Roll-logFile
    {
        #function checks to see if file in question is larger than the paramater specified if it is it will roll a log and delete the oldes log if there are more than x logs.
        param(
            [string]$fileName = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")+".log", 
            [int64]$maxSize = $logSize, 
            [int]$maxCount = $logCount
        )
        $logRollStatus = $true
        if(test-path $filename) {
            $file = Get-ChildItem $filename
            # Start the log-roll if the file is big enough
    
            #Write-Log-Line "$Stamp INFO Log file size is $($file.length), max size $maxSize" $logFile
            #Write-Host "$Stamp INFO Log file size is $('{0:N0}' -f $file.length), max size $('{0:N0}' -f $maxSize)"
            if($file.length -ge $maxSize) {
                Write-Log-Line "$Stamp INFO Log file size $('{0:N0}' -f $file.length) is larger than max size $('{0:N0}' -f $maxSize). Rolling log file!" $logFile
                #Write-Host "$Stamp INFO Log file size $('{0:N0}' -f $file.length) is larger than max size $('{0:N0}' -f $maxSize). Rolling log file!"
                $fileDir = $file.Directory
                $fbase = $file.BaseName
                $fext = $file.Extension
                $fn = $file.name #this gets the name of the file we started with
    
                function refresh-log-files {
                     Get-ChildItem $filedir | ?{ $_.Extension -match "$fext" -and $_.name -like "$fbase*"} | Sort-Object lastwritetime
                }
                function fileByIndex($index) {
                    $fileByIndex = $files | ?{($_.Name).split("-")[-1].trim("$fext") -eq $($index | % tostring 00)}
                    #Write-Log-Line "LOGGER: fileByIndex = $fileByIndex" $logFile
                    $fileByIndex
                }
                function getNumberOfFile($theFile) {
                    $NumberOfFile = $theFile.Name.split("-")[-1].trim("$fext")
                    if ($NumberOfFile -match '[a-z]'){
                        $NumberOfFile = "01"
                    }
                    #Write-Log-Line "LOGGER: GetNumberOfFile = $NumberOfFile" $logFile
                    $NumberOfFile
                }
    
                refresh-log-files | %{
                    [int32]$num = getNumberOfFile $_
                    Write-Log-Line "LOGGER: checking log file number $num" $logFile
                    if ([int32]$($num | % tostring 00) -ge $maxCount) {
                        write-host "Deleting files above log max count $maxCount : $_"
                        Write-Log-Line "LOGGER: Deleting files above log max count $maxCount : $_" $logFile
                        Remove-Item $_.fullName
                    }
                }
    
                $files = @(refresh-log-files)
    
                # Now there should be at most $maxCount files, and the highest number is one less than count, unless there are badly named files, eg non-numbers
                for ($i = $files.count; $i -gt 0; $i--) {
                    $newfilename = "$fbase-$($i | % tostring 00)$fext"
                    #$newfilename = getFileNameByNumber ($i | % tostring 00) 
                    if($i -gt 1) {
                        $fileToMove = fileByIndex($i-1)
                    } else {
                        $fileToMove = $file
                    }
                    if (Test-Path $fileToMove.PSPath) { # If there are holes in sequence, file by index might not exist. The 'hole' will shift to next number, as files below hole are moved to fill it
                        write-host "moving '$fileToMove' => '$newfilename'"
                        #Write-Log-Line "LOGGER: moving $fileToMove => $newfilename" $logFile
                        # $fileToMove is a System.IO.FileInfo, but $newfilename is a string. Move-Item takes a string, so we need full path
                        Move-Item ($fileToMove.FullName) -Destination $fileDir\$newfilename -Force
                    }
                }
            } else {
                $logRollStatus = $false
            }
        } else {
            $logrollStatus = $false
        }
        $LogRollStatus
    }
    
    
    Function Write-Log {
        [CmdletBinding()]
        Param(
        [Parameter(Mandatory=$True)]
        [string]
        $Message,
    
        [Parameter(Mandatory=$False)]
        [String]
        $logFile = "log-$(gc env:computername).log",
    
        [Parameter(Mandatory=$False)]
        [String]
        $Level = "INFO"
        )
        #Write-Host $logFile
        $levels = ("DEBUG","INFO","WARN","ERROR","FATAL")
        $logLevelPos = [array]::IndexOf($levels, $logLevel)
        $levelPos = [array]::IndexOf($levels, $Level)
        $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss:fff")
    
        # First roll the log if needed to null to avoid output
        $Null = @(
            Roll-logFile -fileName $logFile -filesize $logSize -logcount $logCount
        )
    
        if ($logLevelPos -lt 0){
            Write-Log-Line "$Stamp ERROR Wrong logLevel configuration [$logLevel]" $logFile
        }
    
        if ($levelPos -lt 0){
            Write-Log-Line "$Stamp ERROR Wrong log level parameter [$Level]" $logFile
        }
    
        # if level parameter is wrong or configuration is wrong I still want to see the 
        # message in log
        if ($levelPos -lt $logLevelPos -and $levelPos -ge 0 -and $logLevelPos -ge 0){
            return
        }
    
        $Line = "$Stamp $Level $Message"
        Write-Log-Line $Line $logFile
    }
    
    
    Start-Transcript -Path Computer.log
    
    Write-Host "everything will end up in Computer.log"
    
    Stop-Transcript
    
    function WriteLog
    {
        Param ([string]$LogString)
        $LogFile = "C:\$(gc env:computername).log"
        $DateTime = "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
        $LogMessage = "$Datetime $LogString"
        Add-content $LogFile -value $LogMessage
    }
    
    WriteLog "This is my log message"