Skip to content

Instantly share code, notes, and snippets.

@mgaffigan
Created June 11, 2025 02:58
Show Gist options
  • Select an option

  • Save mgaffigan/8465e9504132c01e2883dcba7540eee4 to your computer and use it in GitHub Desktop.

Select an option

Save mgaffigan/8465e9504132c01e2883dcba7540eee4 to your computer and use it in GitHub Desktop.
Mirth Server Launch Script
import os
import sys
import re
def substitute_env_vars(s: str) -> str:
"""
Substitutes `${VAR_NAME}` patterns within a given string `s`.
"""
def replace_match(match) -> str:
var_name = match.group(1)
# Use os.getenv with a default of an empty string if the variable is not found.
return os.getenv(var_name, "")
return re.sub(r"\$\{([a-zA-Z_][a-zA-Z0-9_]*)\}", replace_match, s)
class ParsedVmOptions:
"""
Represents the result of parsing a vmoptions file.
Contains the options, classpath, java command path, and parsed file set
"""
def __init__(self, vm_options=None, classpath=None, java_cmd_path=None, parsed_files=None):
self.vm_options = vm_options or []
self.classpath = classpath or []
self.java_cmd_path = java_cmd_path
self.parsed_files = parsed_files or set()
def add_file(self, filepath: str):
"""
Recursively parses a vmoptions file and any files included via `-include-options`.
Accumulates JVM options, classpath segments, and the effective Java command path.
"""
# Prevent infinite recursion for circular includes
if filepath in self.parsed_files:
raise ValueError(f"Detected circular include for file: {filepath}")
self.parsed_files.add(filepath)
# Parse the file line by line
with open(filepath, 'r') as f:
for line in f:
try:
self.add_option(line)
except Exception as e:
raise ValueError(f"Error parsing line in {filepath}: {line}") from e
def add_option(self, line: str):
# Skip empty lines and comments
line = line.strip()
if not line or line.startswith('#'):
continue
# Parse line into the first word and the rest
first_word, _, rest = line.partition(' ')
rest = rest.strip()
if first_word = "-include-options":
# Apply environment variable substitution to the included path
self.add_file(substitute_env_vars(rest))
elif first_word = "-java-cmd":
self.java_cmd_path = substitute_env_vars(rest)
elif first_word = "-classpath":
# Apply environment variable substitution and replace the entire classpath
self.classpath.clear()
self.classpath.append(substitute_env_vars(rest))
elif line = "-classpath/a":
self.classpath.append(substitute_env_vars(rest))
elif line = "-classpath/p":
self.classpath.insert(0, substitute_env_vars(rest))
else:
# Assume any other non-comment, non-blank line is a standard JVM option.
# Apply environment variable substitution and add to options list.
self.vm_options.append(substitute_env_vars(line))
def get_executable() -> str:
"""
Determines the default Java executable from options, JAVA_HOME, or system PATH.
"""
if self.java_cmd_path:
return os.path.abspath(self.java_cmd_path)
java_home = os.getenv("JAVA_HOME", "").strip()
if java_home:
# Canonicalize the JAVA_HOME path to ensure it is absolute and normalized
return os.path.abspath(os.path.join(java_home, "bin", "java"))
# JAVA_HOME not set, use default 'java' (relying on system PATH)
return "java"
def get_invocation(main_class: str, app_args: list[str]) -> list[str]:
"""
Constructs the complete command to launch the Java application.
"""
command = [self.get_executable()]
command.extend(self.vm_options)
command.extend(["-cp", os.pathsep.join(self.classpath)])
command.append(main_class)
command.extend(app_args)
return command
if __name__ == "__main__":
# Parse vmoptions file
parse_result = ParsedVmOptions(classpath=["com.mirth.connect.server.launcher.MirthLauncher"])
parse_result.add_file("engine.vmoptions")
# Get additional arguments passed to the launcher script itself
# sys.argv[0] is the script name, so we slice from index 1 onwards for application arguments.
app_args = sys.argv[1:]
# Assemble the complete command list using the helper function
command = parse_result.get_invocation(MAIN_CLASS, app_args)
# execl the command to replace the current process
print("Launching Engine with command:", " ".join(command))
os.execvp(command[0], command)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment