Hello PowerCLI gurus
I've been looking on the net for a PowerCLI script that would terminate all VI client sessions that have been idle for x period of time. I've found a post on VMware forums (http://communities.vmware.com/message/914858?z=zI0r8n) but had no luck with it. I've also found a script created by A.Mikkelsen at http://www.amikkelsen.com/?p=384 but that one is not working either.
Following is the actual script by A.Mikkelsen that is based on the code by LucD in the previously mentioned forum.
START
##################################################################################
# The script terminates all idle user sessions if idle for longer that xx #
# #
# Created by: Anders Mikkelsen, 2010 #
##################################################################################
clear
# Add-PSSnapin VMware.VimAutomation.Core
# $server = "vcenter server"
# $user = "vcenter username"
# $pwd = "vcenter password"
# Add 1 hour extra the the time, due to timestamp difference between MSSQL and Windows time.
# 5 hours idle time = 360
# 10 hours idle time = 660
$intOlderThan = 60
# Connect-VIServer $server -User $user -Password $pwd
# Connect-VIServer $server
$svcRef = new-object VMware.Vim.ManagedObjectReference
$svcRef.Type = "ServiceInstance"
$svcRef.Value = "ServiceInstance"
$serviceInstance = get-view $svcRef
$sessMgr = get-view $serviceInstance.Content.sessionManager
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
if (($sess.LastActiveTime).addminutes($intOlderThan) -lt (Get-Date)){
$oldSessions += $sess.Key
#write "$($sess.UserName)"
}
}
# Terminale session than are idle for longer than approved ($intOlderThan)
$sessMgr.TerminateSession($oldSessions)
Disconnect-VIServer * -Confirm:$false
END
The error message I receive is:
START
Exception calling "TerminateSession" with "1" argument(s): "A specified parameter was not correct.
"
At D:\Scripts\vc_terminate_idle_sessions.ps1:36 char:26
+ $sessMgr.TerminateSession <<<< ($oldSessions)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
END
I should mention that my knowledge of PowerCLI is next to nothing so any help in tweaking this script to get it working with PowerCLI 5.1 Release 2 and VC 5 U2 would be much appreciated.
The error is caused by the fact that you are trying to kill your own session (if it was started longer than the time interval ago).
Apparently in vSphere 5.* they included a fail-safe mechanism to avoid that.
You can catch this by adding a simple test.
## max number of idle minutes for sessions to keep
$intOlderThan = 60
$serviceInstance = Get-View 'ServiceInstance'
## get the session manager object
$sessMgr = Get-View $serviceInstance.Content.sessionManager
## array to hold info about stale sessions
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
if (($sess.LastActiveTime).addminutes($intOlderThan) -lt (Get-Date) -and
$sess.Key -ne $sessMgr.CurrentSession.Key){
$oldSessions += $sess.Key
} ## end if
} ## end foreach
## if there are any old sessions, terminate them; else, just write message to the Warning stream
if (($oldSessions | Measure-Object).Count -gt 0) {
## Terminate sessions than are idle for longer than approved ($intOlderThan)
$sessMgr.TerminateSession($oldSessions)
} ## end if
else {Write-Warning "No sessions that have been idle for more than '$intOlderThan' minutes; no action taken"}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hello,
I suspect that you might be running into a situation where you have no sessions that have been inactive for longer than the configured time. To help rule that in/out, you could add a check for the number of sessions held in the $oldSessions array -- if greater than 0, then try to terminate them, else, write to the Warning stream that there are no such sessions to terminate. Updated/consolidated a bit:
## max number of idle minutes for sessions to keep
$intOlderThan = 60
$serviceInstance = Get-View 'ServiceInstance'
## get the session manager object
$sessMgr = Get-View $serviceInstance.Content.sessionManager
## array to hold info about stale sessions
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
if (($sess.LastActiveTime).addminutes($intOlderThan) -lt (Get-Date)){
$oldSessions += $sess.Key
} ## end if
} ## end foreach
## if there are any old sessions, terminate them; else, just write message to the Warning stream
if (($oldSessions | Measure-Object).Count -gt 0) {
## Terminate sessions than are idle for longer than approved ($intOlderThan)
$sessMgr.TerminateSession($oldSessions)
} ## end if
else {Write-Warning "No sessions that have been idle for more than '$intOlderThan' minutes; no action taken"}
How does that do for you?
Check out this blog about listing and disconnecting sessions. There are cmdlets available to download and I've been using them successfully to disconnect idle sessions.
http://blogs.vmware.com/vipowershell/2011/09/list-and-disconnect-vcenter-sessions.html
Thank you Matt
Unfortunately that's not the case, I've checked the VI client sessions and there were plenty of sessions that were idle for longer period of time than specified in the script. In any case I've used your script too but to no avail. I get pretty much identical error message:
START ERROR
Exception calling "TerminateSession" with "1" argument(s): "A specified parameter was not correct.
"
At D:\Scripts\vc_terminate_idle_sessions.ps1:17 char:30
+ $sessMgr.TerminateSession <<<< ($oldSessions)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
END ERROR
Cheers
The error is caused by the fact that you are trying to kill your own session (if it was started longer than the time interval ago).
Apparently in vSphere 5.* they included a fail-safe mechanism to avoid that.
You can catch this by adding a simple test.
## max number of idle minutes for sessions to keep
$intOlderThan = 60
$serviceInstance = Get-View 'ServiceInstance'
## get the session manager object
$sessMgr = Get-View $serviceInstance.Content.sessionManager
## array to hold info about stale sessions
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
if (($sess.LastActiveTime).addminutes($intOlderThan) -lt (Get-Date) -and
$sess.Key -ne $sessMgr.CurrentSession.Key){
$oldSessions += $sess.Key
} ## end if
} ## end foreach
## if there are any old sessions, terminate them; else, just write message to the Warning stream
if (($oldSessions | Measure-Object).Count -gt 0) {
## Terminate sessions than are idle for longer than approved ($intOlderThan)
$sessMgr.TerminateSession($oldSessions)
} ## end if
else {Write-Warning "No sessions that have been idle for more than '$intOlderThan' minutes; no action taken"}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Hi LucD
Much appreciate your assistance.
Prior to posting my last post I did make sure that my session was not idle, and it never was showing as idle. Well not in VI client anyway. However, I've tested your script and it works, kind of. Well it actually does terminate all sessions that have been idle for specified or greater period of time but it also terminates my active session.
Not much of a biggie as I'm intending to run the script with a service account which than should get around the issue.
Cheers
Thanks for the catch, Luc.
When I run this script I get a message that no sessions have been idle for over 60 minutes. I actually have many that are well over this time. I am running this against 5.5U3 without luck. If I modify the script for something less than 60 minutes it works for those idle sessions, but once it's over the 60 minutes mark it doesn't seem to see it. Very strange...
EDIT: I was pretty sure it had worked earlier but it looks like its not working regardless of what I set the minute mark at. I always get the message of no sessions being idle for that period of time.
It would be interesting to see the output of the following.
Get-Date
$serviceInstance = Get-View 'ServiceInstance'
$sessMgr = Get-View $serviceInstance.Content.sessionManager
$sessMgr.SessionList | Select UserName,LoginTime,LastActiveTime
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Here is a sampling of the output. I currently have sessions idle for as long as 12 hours...
That long session, could that be your PowerCLI session ?
The script doesn't kill that session.
On the others, when exactly did you run the script ?
That's why I put the Get-Date at the top.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
No, it's not my current session. Having trouble seeing all of the output since it scrolls down and I can't go back up to view or copy.
Try adding a First parameter
$sessMgr.SessionList | Select -First 10 -Property UserName,LoginTime,LastActiveTime
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thursday, February 4, 2016 7:45:23 AM
UserName :
LoginTime : 2/3/2016 11:34:29 PM
LastActiveTime : 2/4/2016 1:44:43 PM
UserName :
LoginTime : 2/3/2016 11:34:59 PM
LastActiveTime : 2/3/2016 11:34:59 PM
UserName :
LoginTime : 1/31/2016 1:58:00 AM
LastActiveTime : 2/4/2016 1:43:34 PM
UserName :
LoginTime : 1/29/2016 3:01:30 PM
LastActiveTime : 2/4/2016 12:46:43 PM
UserName :
LoginTime : 1/29/2016 5:22:02 PM
LastActiveTime : 2/4/2016 1:35:02 PM
UserName :
LoginTime : 2/4/2016 9:35:19 AM
LastActiveTime : 2/4/2016 9:35:19 AM
UserName :
LoginTime : 2/4/2016 1:39:18 PM
LastActiveTime : 2/4/2016 1:45:18 PM
UserName :
LoginTime : 2/3/2016 10:32:49 PM
LastActiveTime : 2/3/2016 10:33:00 PM
UserName :
LoginTime : 2/4/2016 1:43:03 PM
LastActiveTime : 2/4/2016 1:45:03 PM
Could it be that you have sessions from different timezones ?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
I don't believe that is the issue. I will keep digging around and try to figure it out. Here are a couple more views for what it's worth. Thanks for trying to help out.
Apparently I am not running all of the code? I pulled the below thinking this is all I needed?
## max number of idle minutes for sessions to keep
$intOlderThan = 60
$serviceInstance = Get-View 'ServiceInstance'
## get the session manager object
$sessMgr = Get-View $serviceInstance.Content.sessionManager
## array to hold info about stale sessions
$oldSessions = @()
foreach ($sess in $sessMgr.SessionList){
if (($sess.LastActiveTime).addminutes($intOlderThan) -lt (Get-Date) -and
$sess.Key -ne $sessMgr.CurrentSession.Key){
$oldSessions += $sess.Key
} ## end if
} ## end foreach
## if there are any old sessions, terminate them; else, just write message to the Warning stream
if (($oldSessions | Measure-Object).Count -gt 0) {
## Terminate sessions than are idle for longer than approved ($intOlderThan)
$sessMgr.TerminateSession($oldSessions)
} ## end if
else {Write-Warning "No sessions that have been idle for more than '$intOlderThan' minutes; no action taken"}
That looks complete.
That code, kills sessions that haven't been active for a specific amount of time.
To get a complete view you might want to run the code in my Get complete vCenter session info post.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
The script in the link does work for me and I am able to pull the information on the sessions and source correctly. That being said when I run the script in this thread it does appear to terminate 'some' connections but not all. If I wait several hours between attempting to run the script it does remove some connections, but after that it always says there are none to remove. Even if I keep dropping the session time in the script. I still have tons of connections that are days old and are not removed unless manually done. Still scratching my head on why it's not working as expected for me here. The reason I am even looking into this script is to mask an issue we seem to be having with lots of idles sessions not closing out. It's not uncommon for us to see over 100 connections (active/idle). We are working to try and resolve this but was hoping to put the script in place to help out.