简体   繁体   English

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

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

I have got a powershell script working, the job runs a list of servers, remotely connects to the servers and runs a simple script to get the hostname from the server.我有一个 powershell 脚本在工作,该作业运行服务器列表,远程连接到服务器并运行一个简单的脚本以从服务器获取主机名。 The issue is that it does get stuck on some occasions.问题是它在某些情况下确实会卡住。 I read up on https://4sysops.com/archives/invoke-command-compensating-for-slow-responding-computers/ .我阅读了https://4sysops.com/archives/invoke-command-compensating-for-slow-responding-computers/ I came across the use of jobs where a timeout can be specified.我遇到了可以指定超时的作业的使用。

Here is my complete script and at the moment, it currently hangs on some hosts.这是我的完整脚本,目前它挂在一些主机上。

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

What is the issue.什么问题。

The issue here is that the script above hangs on some hosts, and when that happens the whole process is stuck.这里的问题是上面的脚本挂在某些主机上,当发生这种情况时,整个过程就会卡住。 No errors at all from winRM, this makes automation very difficult, the code also needs to be able to run in parallel as there are over 2,000 hosts. winRM 完全没有错误,这使得自动化非常困难,代码还需要能够并行运行,因为有超过 2,000 台主机。

What have I done?我做了什么?

I introduced powershell jobs, however the issue with this is that I cant seem to be able to get the value of $results, what I want to know is hosts that were successful connection wise, get the value of the host name back and for hosts that timed out, I want to be able to identify them and most importantly use workflows or any other means to run this in parallel, please note that I am on powershell v5.我介绍了 powershell 个工作,但是问题是我似乎无法获得 $results 的值,我想知道的是成功连接的主机,获取主机名的值并返回主机超时,我希望能够识别它们,最重要的是使用工作流或任何其他方式并行运行它,请注意我在 powershell v5.

If the section below is changed to如果以下部分更改为

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

What then happens is that I loose track of the status of the particular server as $result no longer contains the hostname and I have no way to work out which jobs timed out.然后发生的事情是我失去了对特定服务器状态的跟踪,因为 $result 不再包含主机名,而且我无法确定哪些作业超时。

Another solution that could work using my original code snippet is if I can get winrM to gracefully timeout and if there is a way for me to know when this happens so that I can log it for the particular host.另一个可以使用我的原始代码片段的解决方案是,如果我可以让 winrM 正常超时,并且我是否有办法知道这种情况何时发生,以便我可以为特定主机记录它。

Please ignore the hardcoded username/password, its not good practice.请忽略硬编码的用户名/密码,这不是好的做法。 As I am running the script several times, its easier this way then attending to a prompt several times.当我多次运行脚本时,这种方式比多次注意提示更容易。

I would approach the code using New-PSSession with a Try / Catch and a List where you can store the possible errors.我会使用带有Try / CatchNew-PSSession和一个列表来处理代码,您可以在其中存储可能的错误。

The downside is that the loop to establish the connection is linear and it can take time.缺点是建立连接的循环是线性的,可能需要时间。

$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
}

If you wanted something faster but dirtier you can use redirection :如果你想要更快但更脏的东西,你可以使用重定向

$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