From 3b2fca101b76b894683223ec9281c42cfa294459 Mon Sep 17 00:00:00 2001 From: Philip Marzullo Date: Thu, 8 Aug 2019 13:34:23 -0400 Subject: [PATCH] 0003560: Unable to use SymmetricDS service in Ubuntu 18.04 / bionic beaver (Systemd in general) --- .../symmetric/wrapper/UnixService.java | 140 +++++++++++++++--- .../src/main/resources/symmetricds.systemd | 18 +++ 2 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 symmetric-wrapper/src/main/resources/symmetricds.systemd diff --git a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/UnixService.java b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/UnixService.java index 301136db1e..8a9ab445db 100644 --- a/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/UnixService.java +++ b/symmetric-wrapper/src/main/java/org/jumpmind/symmetric/wrapper/UnixService.java @@ -50,8 +50,16 @@ public class UnixService extends WrapperService { private static final String INITD_DIR = "/etc/init.d"; + private static final String SYSTEMD_INSTALL_DIR = "/lib/systemd/system"; + private static final String SYSTEMD_RUNTIME_DIR = "/run/systemd/system"; + private static final String INITD_SCRIPT_START = "start"; private static final String INITD_SCRIPT_STOP = "stop"; + + private static final String SYSTEMD_SCRIPT_START = "start"; + private static final String SYSTEMD_SCRIPT_STOP = "stop"; + private static final String SYSTEMD_SCRIPT_ENABLE = "enable"; + private static final String SYSTEMD_SCRIPT_DISABLE = "disable"; @Override protected boolean setWorkingDirectory(String dir) { @@ -60,13 +68,57 @@ protected boolean setWorkingDirectory(String dir) { @Override public void install() { - String rcDir = getRunCommandDir(); - String runFile = INITD_DIR + "/" + config.getName(); - if (!isPrivileged()) { throw new WrapperException(Constants.RC_MUST_BE_ROOT, 0, "Must be root to install"); } + System.out.println("Installing " + config.getName() + " ..."); + + if(isSystemdRunning()) { + installSystemd(); + } else { + installInitd(); + } + System.out.println("Done"); + } + + private boolean isSystemdRunning() { + File systemddir = new File(SYSTEMD_RUNTIME_DIR); + return systemddir.exists(); + } + + private void installSystemd() { + String runFile = SYSTEMD_INSTALL_DIR + "/" + config.getName() + ".service"; + try(FileWriter writer = new FileWriter(runFile); + BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream( + "/symmetricds.systemd")))) + { + String line = null; + while((line = reader.readLine()) != null) { + line = line.replaceAll("\\$\\{wrapper.description}", config.getDescription()); + line = line.replaceAll("\\$\\{wrapper.pidfile}", getWrapperPidFile()); + line = line.replaceAll("\\$\\{wrapper.home}", config.getWorkingDirectory().getAbsolutePath()); + line = line.replaceAll("\\$\\{wrapper.jarfile}", config.getWrapperJarPath()); + line = line.replaceAll("\\$\\{wrapper.java.command}", config.getJavaCommand()); + line = line.replaceAll("\\$\\{wrapper.run.as.user}", + config.getRunAsUser() == null || config.getRunAsUser().length() == 0 ? "root" : config.getRunAsUser()); + writer.write(line + "\n"); + } + } catch(IOException e) { + throw new WrapperException(Constants.RC_FAIL_INSTALL, 0, "Failed while writing run file", e); + } + runServiceCommand(getSystemdCommand(SYSTEMD_SCRIPT_ENABLE, config.getName())); + } + + private String getWrapperPidFile() throws IOException { + // Make location absolute (starting with / ) + return (config.getWrapperPidFile() != null && config.getWrapperPidFile().startsWith("/") ? config.getWrapperPidFile() : + config.getWorkingDirectory().getCanonicalPath() + "/" + config.getWrapperPidFile()); + } + + private void installInitd() { + String rcDir = getRunCommandDir(); + String runFile = INITD_DIR + "/" + config.getName(); try { FileWriter writer = new FileWriter(runFile); @@ -99,28 +151,42 @@ public void install() { CLibrary.INSTANCE.symlink(runFile, rcDir + "/rc" + runLevel + ".d/K" + RUN_SEQUENCE_STOP + config.getName()); } - System.out.println("Done"); } @Override public void uninstall() { - String rcDir = getRunCommandDir(); - String runFile = INITD_DIR + "/" + config.getName(); if (!isPrivileged()) { throw new WrapperException(Constants.RC_MUST_BE_ROOT, 0, "Must be root to uninstall"); } System.out.println("Uninstalling " + config.getName() + " ..."); + + if(isSystemdRunning()) { + uninstallSystemd(); + } else { + uninstallInitd(); + } - for (String runLevel : RUN_LEVELS_START) { + System.out.println("Done"); + } + + private void uninstallSystemd() { + runServiceCommand(getSystemdCommand(SYSTEMD_SCRIPT_DISABLE, config.getName())); + String runFile = SYSTEMD_INSTALL_DIR + "/" + config.getName() + ".service"; + new File(runFile).delete(); + } + + private void uninstallInitd() { + String rcDir = getRunCommandDir(); + String runFile = INITD_DIR + "/" + config.getName(); + for (String runLevel : RUN_LEVELS_START) { new File(rcDir + "/rc" + runLevel + ".d/S" + RUN_SEQUENCE_START + config.getName()).delete(); } for (String runLevel : RUN_LEVELS_STOP) { new File(rcDir + "/rc" + runLevel + ".d/K" + RUN_SEQUENCE_STOP + config.getName()).delete(); } new File(runFile).delete(); - System.out.println("Done"); } protected String getRunCommandDir() { @@ -142,7 +208,11 @@ public boolean isPrivileged() { @Override public boolean isInstalled() { - return new File(INITD_DIR + "/" + config.getName()).exists(); + if(isSystemdRunning()) { + return new File(SYSTEMD_INSTALL_DIR + "/" + config.getName() + ".service").exists(); + } else { + return new File(INITD_DIR + "/" + config.getName()).exists(); + } } @Override @@ -223,6 +293,14 @@ private ArrayList getServiceCommand(String command) { return s; } + private ArrayList getSystemdCommand(String command, String serviceName) { + ArrayList s = new ArrayList(); + s.add("systemctl"); + s.add(command); + s.add(serviceName); + return s; + } + @Override public void start() { if(isInstalled()) { @@ -236,14 +314,26 @@ public void start() { stopProcesses(true); System.out.println("Waiting for server to start"); - boolean success = true; - if(shouldRunService()) { - success = runServiceCommand(getServiceCommand(INITD_SCRIPT_START)); + if(isSystemdRunning()) { + boolean success = true; + if(shouldRunService()) { + success = runServiceCommand(getSystemdCommand(SYSTEMD_SCRIPT_START, config.getName())); + } else { + super.start(); + } + if (! success) { + throw new WrapperException(Constants.RC_FAIL_EXECUTION, 0, "Server did not start"); + } } else { - super.start(); - } - if (! success) { - throw new WrapperException(Constants.RC_FAIL_EXECUTION, 0, "Server did not start"); + boolean success = true; + if(shouldRunService()) { + success = runServiceCommand(getServiceCommand(INITD_SCRIPT_START)); + } else { + super.start(); + } + if (! success) { + throw new WrapperException(Constants.RC_FAIL_EXECUTION, 0, "Server did not start"); + } } } else { super.start(); @@ -334,11 +424,19 @@ protected void stopProcesses(boolean isStopAbandoned) { } } - if(shouldRunService()) { - runServiceCommand(getServiceCommand(INITD_SCRIPT_STOP)); - } else { - super.stopProcesses(isStopAbandoned); - } + if(isSystemdRunning()) { + if(shouldRunService()) { + runServiceCommand(getSystemdCommand(SYSTEMD_SCRIPT_STOP, config.getName())); + } else { + super.stopProcesses(isStopAbandoned); + } + } else { + if(shouldRunService()) { + runServiceCommand(getServiceCommand(INITD_SCRIPT_STOP)); + } else { + super.stopProcesses(isStopAbandoned); + } + } } else { super.stopProcesses(isStopAbandoned); } diff --git a/symmetric-wrapper/src/main/resources/symmetricds.systemd b/symmetric-wrapper/src/main/resources/symmetricds.systemd new file mode 100644 index 0000000000..63e7ad9e64 --- /dev/null +++ b/symmetric-wrapper/src/main/resources/symmetricds.systemd @@ -0,0 +1,18 @@ +[Unit] +Description=${wrapper.description} +After=network-online.target + +[Service] +Type=forking + +Environment="SYM_HOME=${wrapper.home}" + +ExecStart=${wrapper.java.command} -jar ${wrapper.jarfile} start +ExecStop=${wrapper.java.command} -jar ${wrapper.jarfile} stop +ExecReload=${wrapper.java.command} -jar ${wrapper.jarfile} restart +Restart=no +PIDFile=${wrapper.pidfile} +User=${wrapper.run.as.user} + +[Install] +WantedBy=multi-user.target \ No newline at end of file