question

BorislavVitanov-1003 avatar image
0 Votes"
BorislavVitanov-1003 asked ·

Powershell script to start services.

Hi guys,
I have little bit annoying problem with some services by me. In general by a reboot everything is fine, but the issues come when there are windows update, sometimes they caused services to hang, or took very long etc. So to fix it, I search, test some stuff and create a scheduled task to run 1 hours of the reboot to check for stopped services and run them.

 # Start specific automatic start services not running
 $server = "server1.domain.com"
 $stoppedServices = (Get-WmiObject Win32_Service -ComputerName $server | Where-Object {$_.StartMode -eq 'Auto' -and $_.State -ne "Running"}).Name
 foreach ($stoppedService in $stoppedServices) {
   Write-Host -NoNewline "Starting Server/Service: "; Write-Host -ForegroundColor Green $server"/"$stoppedService
   Get-Service -ComputerName $server -Name $stoppedService | Start-Service
 }

or for example the Citrix services:

 # Script to Manage the Citrix Services at an Citrix Session Host
    
 Get-Service Citrix* -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue
 Get-Service CTX* -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue
 Get-Service BrokerAgent,CdfSvc,MRVCSvc,cpsvc,PvsVmAgent,ServicesManager,StackControlService -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue

which is working fine. I use it as well manually in some cases instead of checking services.msc or server manager. My issue is with 3 different servers:
Wsus server where we have:
- Windows Internal Database with MSSQL$MICROSOFT##WID
- and WsusService
there, I have an issue with starting the DB and then start the services. Basically it should try to start the DB, wait, check again if the DB is running and after this restart WSUSservice if running or start if stopped.

TMMS server where I have: MSSQL$TMMS , TMMSManagementService, MSCSService which should start in this order. I have here some cases when I have to execute manually MSSQL$TMMS 1-2 times because I got Service start time out. And after this I should start the Management service and then MSCSservice (which sometimes starts although others are stopped, and I have to restart when others are up.

But the most annoying server is the Skype for Business server, where I have 3 SQL services and almost 20 Skype for Business services. The Front-End service for examples needs sometime 20 minutes to start while all other services are already running. As SQL I have MSSQL$LYNCLOCAL, MSSQL$RTC, MSSQL$RTCLOCAL.

So, any advice how to make all this start and wait and check again and then continue with others structure? I guess for the $ and # , I have to use ' instead of " , right?

Thanks in advance




windows-server-powershell
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered ·

You could try using something like this:

 foreach ($stoppedService in $stoppedServices) {
     Write-Host -NoNewline "Starting Server/Service: "; Write-Host -ForegroundColor Green $server"/"$stoppedService
         Get-Service -ComputerName $server -Name $stoppedService | Start-Service
         $Count = 0
         do{
             Start-Sleep -Seconds 5
             $ServiceState = (Get-Service -ComputerName $server -Name $stoppedService).State
             if ($ServiceState -ne 'Running'){
                 Set-Service  -ComputerName $server -Name $stoppedService -Status Running
                 $Count++
             }
         } While ($ServiceState -ne 'Running' -and $Count -lt 5)
   }

The code needs tweaking, though. A service may be in a "StartPending" state and maybe you'd rather wait, or stop (and then try starting), the service. There may be other conditions you'll encounter, too.

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

MotoX80 avatar image
0 Votes"
MotoX80 answered ·

I think that if these were my servers, I would configure the service control manager to restart them. At least for the critical services.


71628-capture.jpg


If you have to start them in a certain sequence, then you'll need to have more error checking/waiting, etc. Here's a sample for start=auto services. You can tweak the Start-Sleep's to suit a given server's needs.

 Function Starter {
     write-host "Processing these services." 
     $TheseSvcs | write-host 
     ""
     $StartDate = Get-Date              # start the clock 
     while ($true) {
         $svcs = $TheseSvcs | Get-Service  | Where-Object {($_.StartType -eq 'Auto') -and ($_.Status -eq 'Stopped')} 
         "We found {0} stopped services." -f $svcs.count | Write-Host
         if ($svcs.count -eq 0) {
             $script:success = $true              # update variable in correct scope
             return                               # All start=auto services in that group are running 
         }
         Write-Host "Starting the services" 
         $svcs | Start-Service -ErrorAction SilentlyContinue
         Start-Sleep -Seconds 30                    # give them some time to fire up 
         $svcs = $TheseSvcs | Get-Service  | Where-Object {($_.StartType -eq 'Auto') -and ($_.Status -eq 'Stopped')} 
         "We found {0} services that did not start." -f $svcs.count | Write-Host
         if ($svcs.count -eq 0) {          
             $script:success = $true         # update variable in correct scope
             return                          # All start=auto services in that group are running 
         }
         $svcs | Format-Table -Property Name, DisplayName  | Out-String| Write-Host  
         $EndDate = Get-Date            # how long have we been running
         if ((NEW-TIMESPAN –Start $StartDate –End $EndDate).Minutes -gt $MaxRetryMinutes) {
             Write-Host "The services did not start wtihin the max wait limit." 
             $script:success = $false              # update variable in correct scope
             return  
         }
         Start-Sleep -Seconds 30             # How often should we retry? 
         Write-Host  "Retrying" 
     }
    
 }
 $MaxRetryMinutes = 5       # How long do we keep retrying? 
    
 $TheseSvcs = @('power','sysmain','debug*')
 Starter                             # Start the services 
    
 # Example: From past experience, we know that this group is problematic.
 # Some services will successfuly start but after a few minutes they stop/crash.
 # Let's wait a few minutes and double check them again to make sure that they are still running.
 Start-Sleep -Seconds 300 
 Starter                             # Start the services (again) 
    
 if ($Success) {
     Write-Host "Group 1 services all started." 
 } else { 
     Write-Host "Group 1 services did not all start."
     Write-Host "What do we do now????????"
 } 
    
 $TheseSvcs = @('w3svc',"*update*")
 Starter                             # Start the services 
 if ($Success) {
     Write-Host "Group 2 services all started."
 } else {
     Write-Host "Group 2 services did not all start."
     Write-Host "What do we do now????????"
 } 




capture.jpg (44.9 KiB)
· 2 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

And just to add to the complexities, neither of our answers address the problem of service dependence. A service may not start because a dependent service hasn't started.

0 Votes 0 ·
MotoX80 avatar image MotoX80 RichMatheisen-8856 ·

Sometimes the best we can do is to give the user a starting point. They can tweak it from there.

At the place that I used to work, I automated the patch install with a VB script. We had all kinds of gotcha's. If a Cognos cube build was running, we had to delay for certain period until we could let the patch install run. Had to patch the DB servers before the app servers. On some servers, we had to stop services first. And we found that sometime one patch install would cause another patch to be visible after the reboot. Had to patch twice. And I did the same process where the script would start start=auto services if they weren't running.

It seemed like all I ever did was patch servers and deal with the fallout. I feel Borislav's pain.

Amazing how retirement made that pain go away! :) Now I do this for "fun". How sick is that?

0 Votes 0 ·
RichMatheisen-8856 avatar image
0 Votes"
RichMatheisen-8856 answered ·

Patching. Ugh . . . even today the feeling of apprehension remains! And that's with Microsoft making it immeasurably easier! Remember having to download patches individually (after sorting through the available patches for those that applied to each system's O/S and applications) and then determining the order in which they had to be applied or removed? Then keeping your fingers crossed that you hadn't omitted something and inadvertently introduced a system-crashing catastrophe?

I never developed a liking for VB. Most of the scripts I wrote were in Perl . . . until Monad made it's appearance. It was limited, but I learned it. I managed/architected/administered a multi-nation Exchange organization and when PowerShell started to blossom around 2003 I was glad I did.

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BorislavVitanov-1003 avatar image
0 Votes"
BorislavVitanov-1003 answered ·

Hi to everyone,
thank you for your answers. I will check the Starter function to see how it will work. In general, the patching is ok. I've modified and organize a PS script to install updates in background which works pretty fine. The problem is with the updates itself. For example, the server is rebooted, then it begins to install the updates, get to 33 % then make a reboot again and continues, then finally reboot, which I find pretty annoying. Then even that services are set to automatic delayed start, usually they hang. I can give you an example another annoying thing by SfB. It has 19-20 services which starts fast except the Front-End, which needs 15-20 minutes to start and suddenly the Front-End stops one the SfB services which makes no sense.

I've tried this script as well:

 $serviceNames | Foreach-Object -Process {
   $svc = Get-Service -Name $_ "'MSSQL$TMMS', "TMMSManagementService", "MSCSService""
   if ($svc.Status -ne 'Running') {
     $svc.Start()
     while ($svc.Status -ne 'Running') {
       Write-Output "Waiting for $($svc.Name) to start, current status: $($svc.Status)"
       Start-Sleep -seconds 5
     }
   }
   Write-Output "$($svc.Name) is running"
 }

But for some reasons it doesn't detect properly the MSSQL$TMMS service and continues with others. I put it in ' instead of " and still not work.
Thanks

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

MotoX80 avatar image
0 Votes"
MotoX80 answered ·

But for some reasons it doesn't detect properly the MSSQL$TMMS service

You need a comma after $_. That statement would need to be:

  $svc = Get-Service -Name $_, 'MSSQL$TMMS', TMMSManagementService, MSCSService


But that would mean that $svc is going to be a collection of services, and for every name in $Servicenames you would also process those 3 extra services. The rest of the code looks like it is expecting $svc to contain a single service object.

I would think that you would want to include "'MSSQL$TMMS', "TMMSManagementService", "MSCSService"" in the $Servicenames variable.

Rich's point about dependencies got me to realize that I was thinking too much about how I did patching. I didn't name services, I worked with the app support teams and I basically dictated that any service that they needed to be running after a patch cycle and reboot had to be set as start=auto. That's what my VB script looked at.

Since you're identifying the names, you could include the names of any dependent services, and start=auto isn't necessarily a requirement. And we need to account for starting/stopping statuses.

So, line 16 in my script should be:

 $svcs = $TheseSvcs | Get-Service  | Where-Object  ($_.Status -ne 'Running') 



·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BorislavVitanov-1003 avatar image
0 Votes"
BorislavVitanov-1003 answered ·

Hi @MotoX80

I've tried but it didn't start services. I've stopped them manually and executed it over ISE as Administrator.

72502-services.jpg



Thanks


services.jpg (54.3 KiB)
·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

MotoX80 avatar image
0 Votes"
MotoX80 answered ·

I had a bug. I also added some more displays. Use this Starter function.

 Function Starter {
     write-host "Selection criteria is:" 
     $TheseSvcs | write-host 
     ""
     $StartDate = Get-Date              # start the clock
     write-host "Processing these services." 
     $svcs = $TheseSvcs | Get-Service
     $svcs | Format-table -Property Name, DisplayName, StartType, Status  | Out-String | Write-Host 
     while ($true) {
         $svcs = $TheseSvcs | Get-Service  | Where-Object  {$_.Status -ne 'Running'}  
         "We found {0} stopped services." -f $svcs.count | Write-Host
         if ($svcs.count -eq 0) {
             $script:success = $true              # update variable in correct scope
             break                               # All start=auto services in that group are running 
         }
         Write-Host "Starting the services" 
         $svcs | Start-Service -ErrorAction SilentlyContinue
         Start-Sleep -Seconds 30                    # give them some time to fire up 
         $svcs = $TheseSvcs | Get-Service  | Where-Object  {$_.Status -ne 'Running'} 
         "We found {0} services that did not start." -f $svcs.count | Write-Host
         if ($svcs.count -eq 0) {          
             $script:success = $true         # update variable in correct scope
             break                          # All start=auto services in that group are running 
         }
         $svcs | Format-Table -Property Name, DisplayName  | Out-String | Write-Host  
         $EndDate = Get-Date            # how long have we been running
         if ((NEW-TIMESPAN –Start $StartDate –End $EndDate).Minutes -gt $MaxRetryMinutes) {
             Write-Host "The services did not start wtihin the max wait limit." 
             $script:success = $false              # update variable in correct scope
             break  
         }
         Start-Sleep -Seconds 30             # How often should we retry? 
         Write-Host  "Retrying" 
     }
     write-host "Starter is ending. Current status:"
     $svcs = $TheseSvcs | Get-Service
     $svcs | Format-table -Property Name, DisplayName, StartType, Status  | Out-String | Write-Host 
 }
·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

BorislavVitanov-1003 avatar image
0 Votes"
BorislavVitanov-1003 answered ·

Hi @MotoX80

for some reason my previous comment is missing, so I have to write it again.
I've tested on one server with manual, and automatic reboot and everything worked so far. Well now, the big test is coming cause now the windows updates are coming and see how it works with time-outs.
By the way, just to be sure.
Which row is for SQL services (the main services) and which one for the services depending on then and to be checked as well if they are running.
For example as I mentioned at first - group 1 - SfB SQL Services, group 2 - SfB Services.
Thanks

·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.