繁体   English   中英

使用 powershell 作业跟踪 powershell winRM 远程处理 NO winRM 超时

[英]Using powershell jobs to track powershell winRM remoting NO winRM timeout

我有一个 powershell 脚本在工作,该作业运行服务器列表,远程连接到服务器并运行一个简单的脚本以从服务器获取主机名。 问题是它在某些情况下确实会卡住。 我阅读了https://4sysops.com/archives/invoke-command-compensating-for-slow-responding-computers/ 我遇到了可以指定超时的作业的使用。

这是我的完整脚本,目前它挂在一些主机上。

workflow Connect-windows-Servers
{
param(
[string[]] 
$server_list
)


foreach -parallel -throttlelimit 50  ($server_name in $server_list){
write-output "Inside Workflow but outside inline $server_name $(Get-Date)"
    InLineScript {
    $output_status = "" | Select-Object -Property server_name, isError, result 
    $in_server_name = $using:server_name

    write-output "inline  = $in_server_name"
    $username = "my_usersname"
    $password = "my_password"
    $secstr = New-Object -TypeName System.Security.SecureString
    $password.ToCharArray() | foreach-object {$secstr.AppendChar($_)}
    $credentials = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username,$secstr

    $result = Invoke-Command -ComputerName $in_server_name -ScriptBlock {   [System.Net.Dns]::GetHostName() } -ErrorVariable ErrVar  -Credential $credentials
    
    write-output "Error value is $ErrVar"

    if ($ErrVar)
    {
        $output_status.server_name = $in_server_name
        $output_status.isError = $true
        $output_status.result = $ErrVar
        $deployment_output += New-Object -TypeName psobject -Property @{server_name = $in_server_name; isError = $true ; result = $ErrVar } 


        $sql_query = "insert into my_table (servername,isfailed, result) select '$in_server_name','$true','$ErrVar'"
        write-output $sql_query

        Invoke-Sqlcmd -ServerInstance "db_server" -Query $sql_query -Database  "db_name"     

    }     
    else
    {

        $output_status.server_name = $in_server_name
        $output_status.isError = $false
        $output_status.result = $result
        $deployment_output += New-Object -TypeName psobject -Property @{server_name = $in_server_name; isError = $false ; result = $result } 

        $sql_query = "insert into my_table (servername,isfailed, result) select '$in_server_name','$false','$result'"
        write-output $sql_query

        Invoke-Sqlcmd -ServerInstance "db_server" -Query $sql_query -Database  "db_name"       

        }
     }
  }
    }

$list = @('server1',server2)

Connect-windows-Servers -server_list $list

什么问题。

这里的问题是上面的脚本挂在某些主机上,当发生这种情况时,整个过程就会卡住。 winRM 完全没有错误,这使得自动化非常困难,代码还需要能够并行运行,因为有超过 2,000 台主机。

我做了什么?

我介绍了 powershell 个工作,但是问题是我似乎无法获得 $results 的值,我想知道的是成功连接的主机,获取主机名的值并返回主机超时,我希望能够识别它们,最重要的是使用工作流或任何其他方式并行运行它,请注意我在 powershell v5.

如果以下部分更改为

$result = Invoke-Command -ComputerName $in_server_name -ScriptBlock {   [System.Net.Dns]::GetHostName() } -ErrorVariable ErrVar  -Credential $credentials
$result | wait-job timeout (1*60) | Remove-Job

然后发生的事情是我失去了对特定服务器状态的跟踪,因为 $result 不再包含主机名,而且我无法确定哪些作业超时。

另一个可以使用我的原始代码片段的解决方案是,如果我可以让 winrM 正常超时,并且我是否有办法知道这种情况何时发生,以便我可以为特定主机记录它。

请忽略硬编码的用户名/密码,这不是好的做法。 当我多次运行脚本时,这种方式比多次注意提示更容易。

我会使用带有Try / CatchNew-PSSession和一个列表来处理代码,您可以在其中存储可能的错误。

缺点是建立连接的循环是线性的,可能需要时间。

$servers = 'host1', 'host2', 'host3'
$failed  = [Collections.Generic.List[object]]::new()
$session = foreach($server in $servers) {
    try {
        New-PSSession $server -Credential $cred -ErrorAction Stop
    }
    catch {
        $failed.Add([pscustomobject]@{
            Server    = $server
            Exception = $_.ToString()
        })
    }
}

# Highly unlikely this could fail if you could establish a PSSession
if($session) {
    Invoke-Command -SessionName $session -ScriptBlock { [System.Net.Dns]::GetHostName() }
    Remove-PSSession $session
}

if($failed) {
    # Has all records of failed connections with the corresponding error messages
    $failed
}

如果你想要更快但更脏的东西,你可以使用重定向

$servers = 'host1', 'host2', 'host3'
$result  = Invoke-Command -ComputerName $servers -ScriptBlock {
    [System.Net.Dns]::GetHostName()
} -Credential $credential -ErrorAction Continue 2>&1

$failed, $success = $result.where({ $_ -is [System.Management.Automation.ErrorRecord]}, 'Split')
$failed  # => has the possible errors
$success # => has the remote results

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM