【问题标题】:Write-Output inside Invoke-Command scriptblockInvoke-Command 脚本块内的写入输出
【发布时间】:2020-06-02 15:10:21
【问题描述】:

下面是我正在编写的将所有 SQL 作业放入 CSV 文件的脚本。 脚本本身运行良好,但我在错误处理方面遇到了麻烦。 我不知道如何让 Catch 块内的 Out-File 打印到我的本地机器上的文件,而不是我正在运行 Invoke-Command 的远程机器上。 我该如何做到这一点?

谢谢

PS。为了方便没有经验的同事,脚本尽可能完整地写出来

$sqlServers = @("TEST1","TEST2")

$filePath = [Environment]::GetFolderPath("Desktop")

$dateToday = Get-Date -Format “yyMMdd HH:mm"
$dateTodayFile = Get-Date -Format “yyMMdd"

Write-Output "$dateToday $sqlServers" |
    Out-File "$filePath\Log$dateTodayFile.txt" -Append

$output = Invoke-Command -ComputerName $sqlServers -ScriptBlock{

    Try
    {
        Import-Module sqlserver -ErrorAction Stop
    }
    Catch
    {
        Write-Output "$dateToday ERROR $env:computername" |
            Out-File "$filePath\Log$dateTodayFile.txt" -Append
        Exit
    }
    $instances = $env:computername | Foreach-Object {Get-ChildItem -Path "SQLSERVER:\SQL\$_"}

    ForEach ($instance in $instances){

        Try
        {
        $instanceName = $instance.InstanceName
        Get-SqlAgentJob -ServerInstance "$env:computername\$instanceName" -ErrorAction Stop |
            Where-Object {$_.IsEnabled -eq "True" -and $_.LastRunDate -gt [DateTime]::Today.AddDays(-2) -and $_.OwnerLoginName -match "TEST"} |
                Select-Object @{Name=‘Job name‘;Expression={$_.Name}},
                    @{Name=‘Description‘;Expression={$_.Description}},
                    @{Name=‘Instance‘;Expression={$_.Parent -Replace '[][]'}},
                    @{Name=‘Run outcome‘;Expression={$_.LastRunOutcome}},
                    @{Name=‘Run date‘;Expression={$_.LastRunDate}},
                    @{Name=‘Run duration‘;Expression={$_.LastRunDuration}},
                    @{Name=‘Job creator‘;Expression={$_.OwnerLoginName}},
                    @{Name=‘Runs on a schedule‘;Expression={$_.HasSchedule}},
                    @{Name='Schedule Type';Expression={$_.JobSchedules -join ','}}
        }
        Catch
        {
            Write-Output "$dateToday ERROR $env:computername\$instanceName" |
                Out-File "$filePath\Log$dateTodayFile.txt" -Append
            Exit
        }
    }
}
$output | Select-Object -Property * -ExcludeProperty PSComputerName,RunSpaceID,PSShowComputerName |
    Sort-Object "Job name" |
        Export-Csv $filePath\SQLJobInvent$dateTodayFile.csv -NoTypeInformation -Delimiter ";" -Encoding UTF8

Write-Output "$dateToday $filePath" |
    Out-File "$filePath\Log$dateTodayFile.txt" -Append
Write-Output "----------------------------------------" |
    Out-File "$filePath\Log$dateTodayFile.txt" -Append

【问题讨论】:

  • 试着移动你的 try-catch 让它包裹你的整个 ForEach ($instance...) 块?
  • 您没有将 $Vars 传递到您的脚本块中......所以您似乎有范围问题。通常的简单解决方案是使用$Using: 作为要传递到脚本块的 $vars。 [咧嘴一笑]

标签: powershell


【解决方案1】:

您的主要问题是范围。

$dateToday$filePath$dateTodayFile 都在本地计算机上声明,但您试图在未定义的远程计算机(脚本块)上使用它们。

有几种方法可以将变量传递到远程计算机,以下是两种:

# Add desired variable to ArgumentList and define it as a parameter
Invoke-Command -ComputerName $sqlServers -ArgumentList $dateToday,$filePath,$dateTodayFile -ScriptBlock {
  param(
    $folderPath,
    $filePath,
    $dateTodayFile
  )  
  # Do something with our injected variables
  Write-Output "$dateToday ERROR $env:computername" |
    Out-File "$filePath\Log$dateTodayFile.txt" -Append
}

# In PS ver >= 3.0 we can use 'using'
Invoke-Command -ComputerName $serverName -ScriptBlock {Write-Output $using:dateToday}

【讨论】:

  • 谢谢你,救命恩人!两者之间有性能差异吗?我将在几个 00 台 SQL 服务器上运行它
  • 很高兴能帮上忙!我不确定两者之间的性能优势。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多