New daemon start/stop methods for use with Procrun
Added additional entry points GerritLauncher.daemonStart and GerritLauncher.daemonStop for use when hosting Gerrit in some other process. The intention of this is to make it an easy fit to the [Apache Commons Daemon Procrun][1]. This adds an easy way to host Gerrit with embedded Jetty as Windows Service. Also moved a bit of logic in Daemon from anonymous thread into the stop method. [1]: http://commons.apache.org/proper/commons-daemon/procrun.html Change-Id: Ie1fd3b7fceb56e159dc7f02fbcf481b0fcdb08e2
This commit is contained in:
@@ -170,6 +170,50 @@ To install Gerrit into an existing servlet container instead of using
|
|||||||
the embedded Jetty server, see
|
the embedded Jetty server, see
|
||||||
link:install-j2ee.html[J2EE installation].
|
link:install-j2ee.html[J2EE installation].
|
||||||
|
|
||||||
|
[[installation_on_windows]]
|
||||||
|
== Installation on Windows
|
||||||
|
|
||||||
|
If new site is going to be initialized with Bouncy Castle cryptography,
|
||||||
|
ssh-keygen command must be available during the init phase. If you have
|
||||||
|
link:https://git-for-windows.github.io/[Git for Windows] installed,
|
||||||
|
start Command Prompt and temporary add directory with ssh-keygen to the
|
||||||
|
PATH environment variable just before running init command:
|
||||||
|
|
||||||
|
====
|
||||||
|
PATH=%PATH%;c:\Program Files\Git\usr\bin
|
||||||
|
====
|
||||||
|
|
||||||
|
Please note that the path in the above example must not be
|
||||||
|
double-quoted.
|
||||||
|
|
||||||
|
To run the daemon after site initialization execute:
|
||||||
|
|
||||||
|
====
|
||||||
|
cd C:\MY\GERRIT\SITE
|
||||||
|
java.exe -jar bin\gerrit.war daemon --console-log
|
||||||
|
====
|
||||||
|
|
||||||
|
To stop the daemon press Ctrl+C.
|
||||||
|
|
||||||
|
=== Install the daemon as Windows Service
|
||||||
|
|
||||||
|
To install Gerrit as Windows Service use the
|
||||||
|
link:http://commons.apache.org/proper/commons-daemon/procrun.html[Apache
|
||||||
|
Commons Daemon Procrun].
|
||||||
|
|
||||||
|
Sample install command:
|
||||||
|
|
||||||
|
====
|
||||||
|
prunsrv.exe //IS//Gerrit --DisplayName="Gerrit Code Review" --Startup=auto ^
|
||||||
|
--Jvm="C:\Program Files\Java\jre1.8.0_65\bin\server\jvm.dll" ^
|
||||||
|
--Classpath=C:\MY\GERRIT\SITE\bin\gerrit.war ^
|
||||||
|
--LogPath=C:\MY\GERRIT\SITE\logs ^
|
||||||
|
--StartPath=C:\MY\GERRIT\SITE ^
|
||||||
|
--StartMode=jvm --StopMode=jvm ^
|
||||||
|
--StartClass=com.google.gerrit.launcher.GerritLauncher --StartMethod=daemonStart ^
|
||||||
|
--StopClass=com.google.gerrit.launcher.GerritLauncher --StopMethod=daemonStop ^
|
||||||
|
++DependsOn=postgresql-x64-9.4
|
||||||
|
====
|
||||||
|
|
||||||
[[customize]]
|
[[customize]]
|
||||||
== Site Customization
|
== Site Customization
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ public final class GerritLauncher {
|
|||||||
private static final String pkg = "com.google.gerrit.pgm";
|
private static final String pkg = "com.google.gerrit.pgm";
|
||||||
public static final String NOT_ARCHIVED = "NOT_ARCHIVED";
|
public static final String NOT_ARCHIVED = "NOT_ARCHIVED";
|
||||||
|
|
||||||
|
private static ClassLoader daemonClassLoader;
|
||||||
|
|
||||||
public static void main(final String[] argv) throws Exception {
|
public static void main(final String[] argv) throws Exception {
|
||||||
System.exit(mainImpl(argv));
|
System.exit(mainImpl(argv));
|
||||||
}
|
}
|
||||||
@@ -102,6 +104,44 @@ public final class GerritLauncher {
|
|||||||
return invokeProgram(cl, argv);
|
return invokeProgram(cl, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void daemonStart(final String[] argv) throws Exception {
|
||||||
|
if (daemonClassLoader != null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"daemonStart can be called only once per JVM instance");
|
||||||
|
}
|
||||||
|
final ClassLoader cl = libClassLoader(false);
|
||||||
|
Thread.currentThread().setContextClassLoader(cl);
|
||||||
|
|
||||||
|
daemonClassLoader = cl;
|
||||||
|
|
||||||
|
String[] daemonArgv = new String[argv.length + 1];
|
||||||
|
daemonArgv[0] = "daemon";
|
||||||
|
for (int i = 0; i < argv.length; i++) {
|
||||||
|
daemonArgv[i + 1] = argv[i];
|
||||||
|
}
|
||||||
|
int res = invokeProgram(cl, daemonArgv);
|
||||||
|
if (res != 0) {
|
||||||
|
throw new Exception("Unexpected return value: " + res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void daemonStop(final String[] argv) throws Exception {
|
||||||
|
if (daemonClassLoader == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"daemonStop can be called only after call to daemonStop");
|
||||||
|
}
|
||||||
|
String[] daemonArgv = new String[argv.length + 2];
|
||||||
|
daemonArgv[0] = "daemon";
|
||||||
|
daemonArgv[1] = "--stop-only";
|
||||||
|
for (int i = 0; i < argv.length; i++) {
|
||||||
|
daemonArgv[i + 2] = argv[i];
|
||||||
|
}
|
||||||
|
int res = invokeProgram(daemonClassLoader, daemonArgv);
|
||||||
|
if (res != 0) {
|
||||||
|
throw new Exception("Unexpected return value: " + res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isProlog(String cn) {
|
private static boolean isProlog(String cn) {
|
||||||
return "PrologShell".equals(cn) || "Rulec".equals(cn);
|
return "PrologShell".equals(cn) || "Rulec".equals(cn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class Daemon extends SiteProgram {
|
|||||||
private boolean sshd = true;
|
private boolean sshd = true;
|
||||||
|
|
||||||
@Option(name = "--disable-sshd", usage = "Disable the internal SSH daemon")
|
@Option(name = "--disable-sshd", usage = "Disable the internal SSH daemon")
|
||||||
void setDisableSshd(@SuppressWarnings("unused") boolean arg) {
|
void setDisableSshd(@SuppressWarnings("unused") boolean arg) {
|
||||||
sshd = false;
|
sshd = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +150,9 @@ public class Daemon extends SiteProgram {
|
|||||||
usage = "Init site before starting the daemon")
|
usage = "Init site before starting the daemon")
|
||||||
private boolean doInit;
|
private boolean doInit;
|
||||||
|
|
||||||
|
@Option(name = "--stop-only", usage = "Stop the daemon", hidden = true)
|
||||||
|
private boolean stopOnly;
|
||||||
|
|
||||||
private final LifecycleManager manager = new LifecycleManager();
|
private final LifecycleManager manager = new LifecycleManager();
|
||||||
private Injector dbInjector;
|
private Injector dbInjector;
|
||||||
private Injector cfgInjector;
|
private Injector cfgInjector;
|
||||||
@@ -180,6 +183,10 @@ public class Daemon extends SiteProgram {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int run() throws Exception {
|
public int run() throws Exception {
|
||||||
|
if (stopOnly) {
|
||||||
|
RuntimeShutdown.manualShutdown();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (doInit) {
|
if (doInit) {
|
||||||
try {
|
try {
|
||||||
new Init(getSitePath()).run();
|
new Init(getSitePath()).run();
|
||||||
@@ -213,14 +220,7 @@ public class Daemon extends SiteProgram {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
log.info("caught shutdown, cleaning up");
|
log.info("caught shutdown, cleaning up");
|
||||||
if (runId != null) {
|
stop();
|
||||||
try {
|
|
||||||
Files.delete(runFile);
|
|
||||||
} catch (IOException err) {
|
|
||||||
log.warn("failed to delete " + runFile, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
manager.stop();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -312,6 +312,13 @@ public class Daemon extends SiteProgram {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
if (runId != null) {
|
||||||
|
try {
|
||||||
|
Files.delete(runFile);
|
||||||
|
} catch (IOException err) {
|
||||||
|
log.warn("failed to delete " + runFile, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
manager.stop();
|
manager.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ public class RuntimeShutdown {
|
|||||||
cb.waitForShutdown();
|
cb.waitForShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void manualShutdown() {
|
||||||
|
cb.manualShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
private RuntimeShutdown() {
|
private RuntimeShutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +101,11 @@ public class RuntimeShutdown {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void manualShutdown() {
|
||||||
|
Runtime.getRuntime().removeShutdownHook(this);
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
|
||||||
void waitForShutdown() {
|
void waitForShutdown() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
while (!shutdownComplete) {
|
while (!shutdownComplete) {
|
||||||
|
|||||||
Reference in New Issue
Block a user