Skip to main content
1-Visitor
April 19, 2020
Solved

How can I perform a restartAllLocalMethodServers through Command Line?

  • April 19, 2020
  • 2 replies
  • 4554 views

I am working on our company's CI/CD and I want to add logic to perform certain functions when certain files/paths are changed since the last pipeline run.

One of these action is the restartAllLocalMethodServers command found in JConsole.  I'm familiar with running it from JConsole, but can't seem to find a class path to try calling it from command line.

If there is no main function for whatever class this is built into, it'd be worth writing my own java utility class to call it.

How can I perform a restartAllLocalMethodServers through Command Line?

Best answer by bcedar

I figured it out!!!

So when you run

```ps1

Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
```
it gets all of the processes currently running java.exe with that class call... meaning it's a method server.
 
When you start killing those processes and run that command again, new processes will be added to the end (after the servermanager sees the dead server and creates a new process).
 
Since the processid is the methodserver id and is used in the log files, i just need to look for a line in the log of the Last process id in that powershell command that matches "ready.*in.*secs", then i can move onto the next original process id.

Here's the function

function Invoke-SlowlyKillMethodServers {
 <#
 .SYNOPSIS
 Stops Windchill Method Servers one at a time.

 .DESCRIPTION
 Collects a list of currently running java.exe processes using the MethodServerMain class. It stops each process, waiting the string regex 'ready.*in.*secs' to appear in new method server logs.

 .INPUTS
 None. You cannot pipe into this function.

 .OUTPUTS
 None. There are no outputs from this function.

 .EXAMPLE
 PS E:\ptc\Windchill> Invoke-SlowlyKillMethodServers

 944 Logs: 2020-10-07 15:13:07,284 INFO [main] wt.method.server.startup - MethodServer ready (in 71.048 secs).
 12220 Logs: 2020-10-07 15:14:24,352 INFO [main] wt.method.server.startup - MethodServer ready (in 68.979 secs).
 8516 Logs: 2020-10-07 15:15:24,232 INFO [main] wt.method.server.startup - BackgroundMethodServer ready (in 52.078 secs).
 6800 Logs: 2020-10-07 15:16:26,187 INFO [main] wt.method.server.startup - BackgroundWVS ready (in 54.043 secs).
 #>
 [CmdletBinding()]
 param (
 [Parameter()]
 [int32]
 # Number of seconds to wait between stopping processes.
 $Seconds_To_Wait = 120
 )
 $MethodServers = Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
 $InitialMethodServers = $MethodServers | Select-Object -Property ProcessID | ConvertTo-Json -Compress
 foreach ($MethodServer in $MethodServers) {
 Stop-Process -Id $MethodServer.ProcessID -Force
 While (Get-Process -Id $MethodServer.ProcessID 2>$null) {
 Start-Sleep 1
 }
 $EndTime = [datetime]::UtcNow.AddSeconds($Seconds_To_Wait)
 do {
 do {
 $ActiveMethodServers = @()
 $ActiveMethodServers += Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
 } while ($MethodServers.Count -ne $ActiveMethodServers.Count)
 $LatestMethodServerID = $ActiveMethodServers.Where({$true}, 'Last', 1).ProcessID
 $LatestMethodServerLogsTail = Get-ChildItem "$env:WT_HOME\logs" -filter "*$LatestMethodServerID*log4j.log" | Get-Content -Tail 1 
 $LatestMethodServerReadyString = Get-ChildItem "$env:WT_HOME\logs" -filter "*$LatestMethodServerID*log4j.log" | Get-Content | Select-String "ready.*in.*secs"
 $LatestMethodServerReady = [bool]$LatestMethodServerReadyString
 $TimeRemaining = $EndTime - [datetime]::UtcNow
 Write-Progress `
 -Activity "Killing $($MethodServer.ProcessID)..." `
 -Status "Initial Method Servers: $InitialMethodServers" `
 -CurrentOperation "$LatestMethodServerID Logs: $LatestMethodServerLogsTail" `
 -SecondsRemaining $TimeRemaining.TotalSeconds
 } while (-not ($LatestMethodServerReady))
 Write-Output "$LatestMethodServerID Logs: $LatestMethodServerReadyString"
 }
}​
Sorry there's no powershell syntax highlighting in this forum 😞 used C# syntax highlighting instead.

2 replies

14-Alexandrite
April 20, 2020

Hi,
I am not sure if you are aware but you can run "windchill stop" and "windchill start" from a windchill shell.
I have seen this launched from an ant script session an works pretty well.
However, if you are running Windchill as Service you may want to read this article:
https://www.ptc.com/en/support/article/CS116636

This is true also if your windows service is using a service account to launch it.

 

I hope this helps.

bcedar1-VisitorAuthor
1-Visitor
April 20, 2020

Unfortunately that would stop all of Windchill causing system downtime for the users.

 

Not all of our changes will require this.  Most of them just require the method servers to be restarted.  The mbeans restartAllLocalMethodServers does this one at a time.  It'll kill a method server (allow users of that method server to be picked up by another method server causing minimal downtime) then start a new method server, it won't continue until the new method server is responding, then move on to the next one.

 

The result of this is a "sluggish" period rather than a down time period.  Almost more like a brown out than a black out for the windchill service.

14-Alexandrite
April 20, 2020

I did not know about the behavior of restartAllLocalMethodServers, that's really cool!

 

I am not sure if this can help you, but looks like there is a RemoteMethodServers API.

RemoteMethodServer rms = RemoteMethodServer.getDefault();

rms.stopAllServers();

 

 

bcedar1-VisitorAuthorAnswer
1-Visitor
October 7, 2020

I figured it out!!!

So when you run

```ps1

Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
```
it gets all of the processes currently running java.exe with that class call... meaning it's a method server.
 
When you start killing those processes and run that command again, new processes will be added to the end (after the servermanager sees the dead server and creates a new process).
 
Since the processid is the methodserver id and is used in the log files, i just need to look for a line in the log of the Last process id in that powershell command that matches "ready.*in.*secs", then i can move onto the next original process id.

Here's the function

function Invoke-SlowlyKillMethodServers {
 <#
 .SYNOPSIS
 Stops Windchill Method Servers one at a time.

 .DESCRIPTION
 Collects a list of currently running java.exe processes using the MethodServerMain class. It stops each process, waiting the string regex 'ready.*in.*secs' to appear in new method server logs.

 .INPUTS
 None. You cannot pipe into this function.

 .OUTPUTS
 None. There are no outputs from this function.

 .EXAMPLE
 PS E:\ptc\Windchill> Invoke-SlowlyKillMethodServers

 944 Logs: 2020-10-07 15:13:07,284 INFO [main] wt.method.server.startup - MethodServer ready (in 71.048 secs).
 12220 Logs: 2020-10-07 15:14:24,352 INFO [main] wt.method.server.startup - MethodServer ready (in 68.979 secs).
 8516 Logs: 2020-10-07 15:15:24,232 INFO [main] wt.method.server.startup - BackgroundMethodServer ready (in 52.078 secs).
 6800 Logs: 2020-10-07 15:16:26,187 INFO [main] wt.method.server.startup - BackgroundWVS ready (in 54.043 secs).
 #>
 [CmdletBinding()]
 param (
 [Parameter()]
 [int32]
 # Number of seconds to wait between stopping processes.
 $Seconds_To_Wait = 120
 )
 $MethodServers = Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
 $InitialMethodServers = $MethodServers | Select-Object -Property ProcessID | ConvertTo-Json -Compress
 foreach ($MethodServer in $MethodServers) {
 Stop-Process -Id $MethodServer.ProcessID -Force
 While (Get-Process -Id $MethodServer.ProcessID 2>$null) {
 Start-Sleep 1
 }
 $EndTime = [datetime]::UtcNow.AddSeconds($Seconds_To_Wait)
 do {
 do {
 $ActiveMethodServers = @()
 $ActiveMethodServers += Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"
 } while ($MethodServers.Count -ne $ActiveMethodServers.Count)
 $LatestMethodServerID = $ActiveMethodServers.Where({$true}, 'Last', 1).ProcessID
 $LatestMethodServerLogsTail = Get-ChildItem "$env:WT_HOME\logs" -filter "*$LatestMethodServerID*log4j.log" | Get-Content -Tail 1 
 $LatestMethodServerReadyString = Get-ChildItem "$env:WT_HOME\logs" -filter "*$LatestMethodServerID*log4j.log" | Get-Content | Select-String "ready.*in.*secs"
 $LatestMethodServerReady = [bool]$LatestMethodServerReadyString
 $TimeRemaining = $EndTime - [datetime]::UtcNow
 Write-Progress `
 -Activity "Killing $($MethodServer.ProcessID)..." `
 -Status "Initial Method Servers: $InitialMethodServers" `
 -CurrentOperation "$LatestMethodServerID Logs: $LatestMethodServerLogsTail" `
 -SecondsRemaining $TimeRemaining.TotalSeconds
 } while (-not ($LatestMethodServerReady))
 Write-Output "$LatestMethodServerID Logs: $LatestMethodServerReadyString"
 }
}​
Sorry there's no powershell syntax highlighting in this forum 😞 used C# syntax highlighting instead.