如果冻结的 AD 服务器没有响应,PowerShell 调用命令超时

发布于 2025-01-11 09:06:15 字数 1144 浏览 0 评论 0原文

我正在编写一个 PowerShell 脚本,它从所有 AD 服务器读取所有共享并将它们输出到 csv 文件中。同时,脚本保存所有发生的错误并将其输出到错误日志中。该脚本将作为每周任务运行。当我运行脚本时,一切都很顺利,直到它到达已冻结的服务器。在这种情况下,脚本将永远运行,因为它没有从服务器得到答案。

现在我需要添加某种超时,在服务器在特定时间内未收到答案后跳过服务器。我将如何使用现有代码做到这一点?

我的代码:


$computers = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_))
    {
        "$_.domain.com"
    }
})

$remoteCode = {
    Get-SmbShare | Where-Object Path | Get-Acl |
    Select-Object -Property "PSChildName", "Path", "Group", "AccessToString"
}

$results = Invoke-Command -ComputerName $computers -ScriptBlock $remoteCode 2>&1
$errors, $good = $results.Where({$_ -is [System.Management.Automation.ErrorRecord]}, 'Split')

$good | Sort-Object PSComputerName | Select-Object "PSComputerName", "PSChildName", "Path", "Group", @{ Name = "AccessToString"; Expression = { $_.AccessToString -replace("268435456", "FullControl") -replace("-1610612736", "ReadAndExecute")}} | export-csv -path C:\PowerShell\Shares\shares.csv -NoTypeInformation -delimiter ";"

$errors.Exception.Message | Set-Content $error_logfile -Encoding Unicode

I'm writing a PowerShell-Script that reads all shares from all AD-Servers and outputs them into a csv-file. At the same time the script is saving all occuring errors and outputs them into an error-log. The script will be run as a weekly task. When I run the script, all goes well until it gets to a server that has frozen. In that case, the script will just run forever because it gets no answer from the server.

Now I need to add some sort of timeout that skips a server after it doesn't recieve an answer for a specific amount of time. How would I do that with my existing code?

My Code:


$computers = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_))
    {
        "$_.domain.com"
    }
})

$remoteCode = {
    Get-SmbShare | Where-Object Path | Get-Acl |
    Select-Object -Property "PSChildName", "Path", "Group", "AccessToString"
}

$results = Invoke-Command -ComputerName $computers -ScriptBlock $remoteCode 2>&1
$errors, $good = $results.Where({$_ -is [System.Management.Automation.ErrorRecord]}, 'Split')

$good | Sort-Object PSComputerName | Select-Object "PSComputerName", "PSChildName", "Path", "Group", @{ Name = "AccessToString"; Expression = { $_.AccessToString -replace("268435456", "FullControl") -replace("-1610612736", "ReadAndExecute")}} | export-csv -path C:\PowerShell\Shares\shares.csv -NoTypeInformation -delimiter ";"

$errors.Exception.Message | Set-Content $error_logfile -Encoding Unicode

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深者入戏 2025-01-18 09:06:15

注意:这个答案几乎没有用处,在理想的世界中,-OperationTimeout会做它的名字所暗示的事情,但是,作为来自 mklement0 的有用评论 指出:

不幸的是,OperationTimeout会话选项并不像其名称所暗示的那样:请参阅GitHub 问题 #15696。实现实际操作持续时间超时是 GitHub 提案 #5434 的主题,该提案建议向 Invoke-Command 添加 -Timeout 参数。

如果您认为这对于未来版本的 PowerShell 来说是一个很好的实现,请考虑对他的提案进行投票!


您可以将 PSSessionOption操作超时结合使用> 和打开超时低于默认值(3 分钟):

请参阅参数New-PSSessionOption 文档的 部分:

-OpenTimeout
确定客户端计算机等待建立会话连接的时间。当时间间隔到期时,建立连接的命令失败。

-OperationTimeout
确定 WinRM 在启动连接超时之前等待来自实时连接的正连接测试的最长时间。

$timeOut = 30000 # => 30 seconds
$psso = New-PSSessionOption -OpenTimeout $timeOut -OperationTimeout $timeOut

$session = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_)) {
        try {
            New-PSSession -ComputerName "$_.domain.com" -SessionOption $psso
        }
        catch {
            Write-Warning $_.Exception.Message
        }
    }
})

脚本的其余部分是相同的,除了使用 -Session 而不是 -ComputerName 作为 Invoke-Command

$results = Invoke-Command -Session $session -ScriptBlock $remoteCode 2>&1

然后 完成远程连接后,您需要删除 PSSession

Remove-PSSession $session

NOTE: This answer is pretty much useless, in an ideal world, -OperationTimeout would do what it's name implies, however, as the helpful comment from mklement0 states:

Unfortunately, the OperationTimeout session option doesn't do what its name suggests: see GitHub issue #15696. Implementing an actual operation-duration timeout is the subject of GitHub proposal #5434, which suggest adding a -Timeout parameter to Invoke-Command.

If you feel this would be a great implementation for future versions of PowerShell, consider up-voting his proposal!


You could use PSSessionOption with a Operation Timeout and Open Timeout below the default values (3 minutes):

See the Parameter section of New-PSSessionOption documentation:

-OpenTimeout
Determines how long the client computer waits for the session connection to be established. When the interval expires, the command to establish the connection fails.

-OperationTimeout
Determines the maximum time WinRM waits for positive connection tests from a live connection before initiating a connection time-out.

$timeOut = 30000 # => 30 seconds
$psso = New-PSSessionOption -OpenTimeout $timeOut -OperationTimeout $timeOut

$session = (Get-Content C:\PowerShell\Shares\serverlist.txt).ForEach({
    if(-not [string]::IsNullOrWhiteSpace($_)) {
        try {
            New-PSSession -ComputerName "$_.domain.com" -SessionOption $psso
        }
        catch {
            Write-Warning $_.Exception.Message
        }
    }
})

Then the rest of the script is the same, except for the use of -Session instead -ComputerName for Invoke-Command:

$results = Invoke-Command -Session $session -ScriptBlock $remoteCode 2>&1

And lastly, after you're done with the remote connections, you would need to remove the PSSessions:

Remove-PSSession $session
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文