The company I work for has a powershell based deployment process for deploying a web application to many internal web and database servers. We use remote powershell sessions and winrm to run an installation script on the target computer after deploying a zip file, and while this works beautifully on most servers, we have one problem child.
The part that has me very confused is why this same script runs fine on 4 other servers but not this one. I'm not sure what the OS version is on the others where it is working, but I can find out if that is relevant.
We are opening a new session, running an installation script, and afterwards are following it with a call to Remove-PSSession -Session $remoteSession, but wsmprovhost.exe never terminates. It will stay running for days until we reboot the server or restart the WinRM service. After we hit our five concurrent session limit, any attempts to open a new session as the domain account we use to run all this, we get an error saying we've hit our limit for open sessions.
I've done some searching and have found many suggestions, which have all turned out to be dead ends. These two posts are similar to my issue, but in the end didn't yield any fixes:
- http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/e17f3665-4d0b-445b-9ce6-f42013ceaffd
- http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/99ea167d-fde3-4ccb-b1ed-0a425980cd62
Version Info for the target box:
PS C:\Windows\system32> $PSVersionTable Name Value ---- ----- CLRVersion 2.0.50727.5466 BuildVersion 6.1.7601.17514 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1
Version Info for the box that is initiating the connection:
Name Value ---- ----- CLRVersion 2.0.50727.4234 BuildVersion 6.0.6002.18111 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1
Some other tid-bits about our environment:
- This is an internal QA server that we use to test our software.
- The deployment is initiated via a powershell script, which is run as a domain account. Both boxes are on the same domain. There is a windows service (Cruise Control) running on the source box as a domain account, and it spawns powershell.exe with appropriate parameters to start the process.
- The source server that initiates the deployment is server 2008 and the box we are deploying to is 2008 R2
- When we hit our concurrent session limit, I went to the target server and enumerated open shells, and this is what it told me:
PS C:\Windows\system32> Get-WSManInstance -ConnectionURI 'http://localhost:5985/wsman' -ResourceURI shell -Enumerate rsp : http://schemas.microsoft.com/wbem/wsman/1/windows/shell lang : en-US ShellId : FB73A939-3CB6-415C-AB55-2F7B2B72E6BC ResourceUri : http://schemas.microsoft.com/powershell/Microsoft.PowerShell Owner : MYDOMAIN\CruiseControl ClientIP : 10.68.82.225 IdleTimeOut : PT180.000S InputStreams : stdin pr OutputStreams : stdout ShellRunTime : P4DT12H37M58S ShellInactivity : P4DT12H23M19S MemoryUsed : 60MB ChildProcesses : 0 rsp : http://schemas.microsoft.com/wbem/wsman/1/windows/shell lang : en-US ShellId : ECD72634-20F0-49BC-8075-59D306F696BE ResourceUri : http://schemas.microsoft.com/powershell/Microsoft.PowerShell Owner : MYDOMAIN\CruiseControl ClientIP : 10.68.82.225 IdleTimeOut : PT180.000S InputStreams : stdin pr OutputStreams : stdout ShellRunTime : P4DT12H7M55S ShellInactivity : P4DT11H53M17S MemoryUsed : 61MB ChildProcesses : 0 rsp : http://schemas.microsoft.com/wbem/wsman/1/windows/shell lang : en-US ShellId : CF934340-34AF-48E1-ACCE-3CBE7DF1DFC4 ResourceUri : http://schemas.microsoft.com/powershell/Microsoft.PowerShell Owner : MYDOMAIN\CruiseControl ClientIP : 10.68.82.225 IdleTimeOut : PT180.000S InputStreams : stdin pr OutputStreams : stdout ShellRunTime : P4DT11H52M53S ShellInactivity : P4DT11H38M16S MemoryUsed : 59MB ChildProcesses : 0 rsp : http://schemas.microsoft.com/wbem/wsman/1/windows/shell lang : en-US ShellId : C8A1C9E4-3818-490E-B1FF-E2D4C7B8716C ResourceUri : http://schemas.microsoft.com/powershell/Microsoft.PowerShell Owner : MYDOMAIN\CruiseControl ClientIP : 10.68.82.225 IdleTimeOut : PT180.000S InputStreams : stdin pr OutputStreams : stdout ShellRunTime : P4DT11H37M52S ShellInactivity : P4DT11H23M12S MemoryUsed : 61MB ChildProcesses : 0 rsp : http://schemas.microsoft.com/wbem/wsman/1/windows/shell lang : en-US ShellId : A1420013-FF1F-4C68-A198-A2C0C7448B0C ResourceUri : http://schemas.microsoft.com/powershell/Microsoft.PowerShell Owner : MYDOMAIN\CruiseControl ClientIP : 10.68.82.225 IdleTimeOut : PT180.000S InputStreams : stdin pr OutputStreams : stdout ShellRunTime : P4DT12H22M57S ShellInactivity : P4DT12H8M21S MemoryUsed : 61MB ChildProcesses : 0
This the part of the script that is supposed to open and close connections. This executes with $ErrorActionPreference = 'Stop'.
C:\Windows\system32\net.exe use /delete /y $Config.Deployment.ShareToDeployTo C:\Windows\system32\net.exe use $Config.Deployment.ShareToDeployTo $Config.Deployment.RemoteUserPassword "/USER:$($Config.Deployment.RemoteUserName)" if (Test-Path $destinationZipPathAsShare) { Remove-Item -Force $destinationZipPathAsShare } if (Test-Path $destinationUnzipDirAsShare) { Remove-Item -Recurse -Force $destinationUnzipDirAsShare } Copy-Item -Path $DeploymentZipFile -Destination $destinationZipPathAsShare if ($Config.Deployment.RemoteUserName) { $password = ConvertTo-SecureString -AsPlainText $Config.Deployment.RemoteUserPassword -Force $credential = New-Object System.Management.Automation.PSCredential -ArgumentList $Config.Deployment.RemoteUserName,$password $remoteSession = New-PSSession $Config.Deployment.ComputerToDeployTo -Credential $credential -UseSSL } else { $remoteSession = New-PSSession $Config.Deployment.ComputerToDeployTo } try { Invoke-Command ` -Session $remoteSession ` -ScriptBlock { param ($exe,$out) & $exe $('-o'+$out) } ` -ArgumentList @($destinationZipPathAsLocal,$destinationUnzipDirAsLocal) Remove-Item -Force $destinationZipPathAsShare Copy-Item -Path $Config.BranchSed -Destination $destinationBranchSedAsShare Copy-Item -Path $Config.Deployment.ClientLogo -Destination $destinationClientLogoAsShare Copy-Item -Path $Config.Deployment.ReportsLogo -Destination $destinationReportsLogoAsShare $installScriptArgs = New-Object "System.Collections.Generic.List[string]" $installScriptArgs.Add($destinationInstallScriptAsLocal) $installScriptArgs.Add($Config.EnvironmentName) $installScriptArgs.Add($Config.Deployment.DeploymentDirAsLocal) $installScriptArgs.Add($Config.Deployment.WebsitesDirAsLocal) $installScriptArgs.Add($Config.Deployment.ComputerToDeployPortalTo) $installScriptArgs.Add($Config.Deployment.LMSContentDirectory) $installScriptArgs.Add($destinationBranchSedAsLocal) $installScriptArgs.Add($destinationClientLogoAsLocal) $installScriptArgs.Add($destinationReportsLogoAsLocal) Invoke-Command ` -Session $remoteSession ` -ScriptBlock { param ($script,$a1,$a2,$a3,$a4,$a5,$a6,$a7,$a8) . $script -SiteName "$a1" -DeploymentsFolder "$a2" -WebsitesFolder "$a3" -PortalVpcPath "$a4" -LMSContentPath "$a5" -BranchSed "$a6" -ClientLogo "$a7" -ReportsLogo "$a8" } ` -ArgumentList $installScriptArgs } finally { Remove-PSSession -Session $remoteSession }
The first Invoke-Command call here is self extracting archive created with 7-Zip. The second is a call to our installation script.
Sorry for the penultimate post, and thanks in advance for any advice/help. You guys rock!
nick