cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Learn all about PTC Community Badges. Engage with PTC and see how many you can earn! X

How can I perform a restartAllLocalMethodServers through Command Line?

bcedar
14-Alexandrite

How can I perform a restartAllLocalMethodServers through Command Line?

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?

ACCEPTED SOLUTION

Accepted Solutions
bcedar
14-Alexandrite
(To: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.

View solution in original post

10 REPLIES 10
aacciano3
14-Alexandrite
(To:bcedar)

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.

bcedar
14-Alexandrite
(To:aacciano3)

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.

aacciano3
14-Alexandrite
(To:bcedar)

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();

 

 

aacciano3
14-Alexandrite
(To:bcedar)

Found the class for restartAllLocalMethodServers method:

wt.manager.jmx.MethodServerMProxy

 

Not sure how you can run your method.

Let me know if you are able to run it.

aacciano3
14-Alexandrite
(To:aacciano3)

@bcedar 

 

Could you please share the code on how were you able to use the restartAllLocalMethodServers API?

Hi

 

I 'm not sure this will help but what I understood is you need to restart only your Method servers. If you are not running a clustered environnement this can be achieved by a kill -9 of all your Method servers, the the ServerManager will restart new ones. To be able to kill all Your Method server on linux you can create a specific alias for windchill (ie wcms) command and configure your windchill starting property to use that command instead of windchill, then you will be able to kill all MethodServer process by filtering based on the specific  command name:

 

ps ax | grep <snippet> | grep -v grep | awk '{print $1}' | xargs kill

If you have background method servers or Queues MethodServer make sûre to adapt this method

 

Hope this helps. 

 

Regards,

 

bcedar
14-Alexandrite
(To:PASI-Consulting)

That's not a bad idea.  Although i fear this wouldn't be very graceful.  I'm in a windows environment so greping around for me, unfortunately.

bcedar
14-Alexandrite
(To:PASI-Consulting)

Here's what I came up with.  Was thinking about trying to figure out when a new method got spun up and when it was "ready" but that was getting stupid fast.  Starting with this for now.

function Invoke-SlowlyKillMethodServers {
    [CmdletBinding()]
    param (
        [Parameter()]
        [int32]
        $Seconds_To_Wait = 60
    )
    $MethodServers = Get-WmiObject Win32_Process -Filter "name = 'java.exe'" | Where-Object CommandLine -Match "MethodServerMain"

    foreach ($MethodServer in $MethodServers) {
        Stop-Process -Id $MethodServer.ProcessID -Force
        While (Get-Process -Id $MethodServer.ProcessID) {
            Start-Sleep 1
        }
        Start-Sleep $Seconds_To_Wait
    }
}
bcedar
14-Alexandrite
(To:bcedar)

I still have not figured out how to do this... i'm thinking it'll require the use of a jmxclient jar.  Haven't made it any further on this though.  Am thinking about writing a utility class if i'm able to import the class.

bcedar
14-Alexandrite
(To: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.
Announcements

Top Tags