A few days ago I got a question on Twitter on how to push a long running command to the background but would also survive a user logoff. This is a pretty standard practice in the Linux world. In PowerShell we've had similar operations using the Start-Job cmdlet. With Start-Job you can run a scriptblock or script in a background PowerShell process and get the results later. However, if you close your PowerShell session, you lose the job so that's not an option here.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The best solution in this case is to take advantage of disconnected sessions. This feature was added in PowerShell 3.0 where Microsoft moved the maintaining the remoting session from the client to the server. This meant that if you had a long running command you wanted to run on a remote server, you could kick it off with Invoke-Command.
Invoke-Command –scriptblock { <some long running series of commands> } –computername chi-foo –inDisconnectedSession
The session gets created remotely and the command kicks off. On the client you can logoff, shut down, go home, or even go to another computer. You can reconnect the session as long as you use the same credentials. One thing you can't do though is be in the middle of an interactive session and decide to disconnect.
It turns out this same idea works locally as well. Here's how I can kick it off
Invoke-Command –scriptblock { $l = get-eventlog system –newest 500 } –computername . –indisconnectedsession
Kicking off a disconnected command (Image Credit: Jeff Hicks)
Remember this is on my machine. Essentially I've created a remote session to myself. I can now close the PowerShell session. I can even log off and go home. BUT, I can't shut down the computer. If I do that, then I will lose the remoting session. For the sake of my demo, I'll log out, re-login and open a new PowerShell session.
Once back in I need to get the disconnected session. You might think to simply run Get-PSSession.
Attempting to reconnect the session (Image Credit: Jeff Hicks)
But this is only trying to show connected sessions. Because the disconnected session is technically remote, I need to specify the computername.
Viewing the disconnected session (Image Credit: Jeff Hicks)
There it is. In order to use it I need to connect to it.
$s = get-pssession –computername . | connect-pssession
Re-connecting the session (Image Credit: Jeff Hicks)
See the availability state of Busy? Even though I am connected to the session I can't get anything out of it until it stops being busy.
Session must be opened and available (Image Credit: Jeff Hicks)
During the course of my testing, and I don't know if this is something related to running this in basically a loopback, but the session never seems to stop being busy, even though if it is simply running my command it should be finished. But if I enter the session interactive, that seems to be enough to give it a bump and get things moving.
Re-entering the disconnected session (Image Credit: Jeff Hicks)
But I'm good with this. I can kick off a long running PowerShell task, logout, and get the results the next time I log in. I can re-use the session for as long as it is open.
An open loopback remoting session (Image Credit: Jeff Hicks)
The session will exist until I delete it. Or I can disconnect it again.
If you find this little trick useful, I hope you'll let me know. And if you want to learn more about PowerShell remoting, keep an eye on the Pluralsight course catalog as I am currently working on a PowerShell Remoting Fundamentals course.
I just wanted to say…
Great Job
Thank you