Merge changes from topic 'win32'
* changes: New daemon start/stop methods for use with Procrun Correctly call ssh-keygen on Win32 with empty passphrase Redirect output from ssh-keygen call to console to see potential errors
This commit is contained in:
@@ -172,6 +172,50 @@ To install Gerrit into an existing servlet container instead of using
|
||||
the embedded Jetty server, see
|
||||
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]]
|
||||
== Site Customization
|
||||
|
@@ -55,6 +55,8 @@ public final class GerritLauncher {
|
||||
private static final String pkg = "com.google.gerrit.pgm";
|
||||
public static final String NOT_ARCHIVED = "NOT_ARCHIVED";
|
||||
|
||||
private static ClassLoader daemonClassLoader;
|
||||
|
||||
public static void main(final String[] argv) throws Exception {
|
||||
System.exit(mainImpl(argv));
|
||||
}
|
||||
@@ -102,6 +104,44 @@ public final class GerritLauncher {
|
||||
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) {
|
||||
return "PrologShell".equals(cn) || "Rulec".equals(cn);
|
||||
}
|
||||
|
@@ -125,7 +125,7 @@ public class Daemon extends SiteProgram {
|
||||
private boolean sshd = true;
|
||||
|
||||
@Option(name = "--disable-sshd", usage = "Disable the internal SSH daemon")
|
||||
void setDisableSshd(@SuppressWarnings("unused") boolean arg) {
|
||||
void setDisableSshd(@SuppressWarnings("unused") boolean arg) {
|
||||
sshd = false;
|
||||
}
|
||||
|
||||
@@ -151,6 +151,9 @@ public class Daemon extends SiteProgram {
|
||||
usage = "Init site before starting the daemon")
|
||||
private boolean doInit;
|
||||
|
||||
@Option(name = "--stop-only", usage = "Stop the daemon", hidden = true)
|
||||
private boolean stopOnly;
|
||||
|
||||
private final LifecycleManager manager = new LifecycleManager();
|
||||
private Injector dbInjector;
|
||||
private Injector cfgInjector;
|
||||
@@ -181,6 +184,10 @@ public class Daemon extends SiteProgram {
|
||||
|
||||
@Override
|
||||
public int run() throws Exception {
|
||||
if (stopOnly) {
|
||||
RuntimeShutdown.manualShutdown();
|
||||
return 0;
|
||||
}
|
||||
if (doInit) {
|
||||
try {
|
||||
new Init(getSitePath()).run();
|
||||
@@ -214,14 +221,7 @@ public class Daemon extends SiteProgram {
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("caught shutdown, cleaning up");
|
||||
if (runId != null) {
|
||||
try {
|
||||
Files.delete(runFile);
|
||||
} catch (IOException err) {
|
||||
log.warn("failed to delete " + runFile, err);
|
||||
}
|
||||
}
|
||||
manager.stop();
|
||||
stop();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -313,6 +313,13 @@ public class Daemon extends SiteProgram {
|
||||
|
||||
@VisibleForTesting
|
||||
public void stop() {
|
||||
if (runId != null) {
|
||||
try {
|
||||
Files.delete(runFile);
|
||||
} catch (IOException err) {
|
||||
log.warn("failed to delete " + runFile, err);
|
||||
}
|
||||
}
|
||||
manager.stop();
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@ import com.google.gerrit.pgm.init.api.ConsoleUI;
|
||||
import com.google.gerrit.pgm.init.api.InitStep;
|
||||
import com.google.gerrit.pgm.init.api.Section;
|
||||
import com.google.gerrit.server.config.SitePaths;
|
||||
import com.google.gerrit.server.util.HostPlatform;
|
||||
import com.google.gerrit.server.util.SocketUtil;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
@@ -31,6 +32,7 @@ import org.apache.sshd.common.util.SecurityUtils;
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -103,25 +105,30 @@ class InitSshd implements InitStep {
|
||||
//
|
||||
final String comment = "gerrit-code-review@" + hostname();
|
||||
|
||||
// Workaround for JDK-6518827 - zero-length argument ignored on Win32
|
||||
String emptyPassphraseArg = HostPlatform.isWin32() ? "\"\"" : "";
|
||||
|
||||
System.err.print(" rsa...");
|
||||
System.err.flush();
|
||||
Runtime.getRuntime().exec(new String[] {"ssh-keygen",
|
||||
new ProcessBuilder("ssh-keygen",
|
||||
"-q" /* quiet */,
|
||||
"-t", "rsa",
|
||||
"-P", "",
|
||||
"-P", emptyPassphraseArg,
|
||||
"-C", comment,
|
||||
"-f", site.ssh_rsa.toAbsolutePath().toString(),
|
||||
}).waitFor();
|
||||
"-f", site.ssh_rsa.toAbsolutePath().toString()
|
||||
).redirectError(Redirect.INHERIT).redirectOutput(Redirect.INHERIT)
|
||||
.start().waitFor();
|
||||
|
||||
System.err.print(" dsa...");
|
||||
System.err.flush();
|
||||
Runtime.getRuntime().exec(new String[] {"ssh-keygen",
|
||||
new ProcessBuilder("ssh-keygen",
|
||||
"-q" /* quiet */,
|
||||
"-t", "dsa",
|
||||
"-P", "",
|
||||
"-P", emptyPassphraseArg,
|
||||
"-C", comment,
|
||||
"-f", site.ssh_dsa.toAbsolutePath().toString(),
|
||||
}).waitFor();
|
||||
"-f", site.ssh_dsa.toAbsolutePath().toString()
|
||||
).redirectError(Redirect.INHERIT).redirectOutput(Redirect.INHERIT)
|
||||
.start().waitFor();
|
||||
|
||||
} else {
|
||||
// Generate the SSH daemon host key ourselves. This is complex
|
||||
|
@@ -39,6 +39,10 @@ public class RuntimeShutdown {
|
||||
cb.waitForShutdown();
|
||||
}
|
||||
|
||||
public static void manualShutdown() {
|
||||
cb.manualShutdown();
|
||||
}
|
||||
|
||||
private RuntimeShutdown() {
|
||||
}
|
||||
|
||||
@@ -96,6 +100,11 @@ public class RuntimeShutdown {
|
||||
}
|
||||
}
|
||||
|
||||
void manualShutdown() {
|
||||
Runtime.getRuntime().removeShutdownHook(this);
|
||||
run();
|
||||
}
|
||||
|
||||
void waitForShutdown() {
|
||||
synchronized (this) {
|
||||
while (!shutdownComplete) {
|
||||
|
Reference in New Issue
Block a user