You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by jo...@apache.org on 2022/07/26 08:25:01 UTC

[jackrabbit-oak] branch OAK-9849 created (now 39423f2292)

This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a change to branch OAK-9849
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git


      at 39423f2292 OAK-9849 write a stacktrace when oak-run is interrupted

This branch includes the following new commits:

     new afc5f8c3f3 refactoring: all commands return the final status code (instead using system.exit directly)
     new ab30c478c3 return the statuscode as returned by the commands
     new 39423f2292 OAK-9849 write a stacktrace when oak-run is interrupted

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[jackrabbit-oak] 03/03: OAK-9849 write a stacktrace when oak-run is interrupted

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a commit to branch OAK-9849
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 39423f2292a568d4d6675890428032694e875e3a
Author: Joerg Hoh <jh...@adobe.com>
AuthorDate: Tue Jul 26 10:23:48 2022 +0200

    OAK-9849 write a stacktrace when oak-run is interrupted
---
 .../org/apache/jackrabbit/oak/run/HelpCommand.java |  2 +-
 .../java/org/apache/jackrabbit/oak/run/Main.java   | 29 ++++++++++++++++++++--
 .../java/org/apache/jackrabbit/oak/run/Utils.java  | 12 +++++++++
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
index d899eb13ab..06fb1bcd76 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
@@ -28,7 +28,7 @@ class HelpCommand implements Command {
     public int execute(String... args) throws Exception {
         System.err.print("Available run modes: ");
         System.err.println(Joiner.on(", ").join(MODES.getModes()));
-        return 1;
+        return 0;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
index ebcf448405..e29b1fdf7a 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
@@ -19,6 +19,10 @@ package org.apache.jackrabbit.oak.run;
 import org.apache.jackrabbit.oak.run.commons.Command;
 import org.apache.jackrabbit.oak.run.commons.Utils;
 
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.Arrays;
 import java.util.Locale;
 
 import static java.util.Arrays.copyOfRange;
@@ -29,7 +33,25 @@ public final class Main {
         // Prevent instantiation.
     }
 
+    public static boolean wasInterrupted = true;
+
+    public static final String PROP_PRINT_STACK = "printStackTraceOnSignal";
+
+    public static Thread interruptionHandler = new Thread( () -> {
+        if (wasInterrupted) {
+            System.err.println("oak-run was interrupted by a signal and stops");
+            if (System.getProperty(PROP_PRINT_STACK) != null) {
+                System.err.println("Dumping threads as requested");
+                ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+                for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(true, true)) {
+                    System.err.println(org.apache.jackrabbit.oak.run.Utils.formatThreadInfo(threadInfo));
+                }
+            }
+         }
+    });
+
     public static void main(String[] args) throws Exception {
+        Runtime.getRuntime().addShutdownHook(interruptionHandler);
         Utils.printProductInfo(
             args,
             Main.class.getResourceAsStream("/META-INF/maven/org.apache.jackrabbit/oak-run/pom.properties"));
@@ -46,8 +68,11 @@ public final class Main {
             args = copyOfRange(args, 1, args.length);
         }
 
-        int statuscode = command.execute(args);
+        int exitcode = command.execute(args);
+        wasInterrupted = false;
+        // when this point is reached, the interruptionHandler is no longer required; there is a slight
+        // chance that the signal is arriving now, but we just ignore this case.
         
-        System.exit(statuscode);
+        System.exit(exitcode);
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Utils.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Utils.java
index ab69802384..c20d8a3c69 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Utils.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Utils.java
@@ -28,6 +28,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.lang.management.ThreadInfo;
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.Enumeration;
@@ -371,6 +372,17 @@ class Utils {
         return closer;
     }
 
+    public static String formatThreadInfo(ThreadInfo threadInfo) {
+        StringBuilder threadDumpDescription = new StringBuilder();
+        threadDumpDescription.append(String.format("\"%s\" java.lang.Thread.State: %s",
+                threadInfo.getThreadName(), threadInfo.getThreadState()));
+        for (StackTraceElement stackTraceElement : threadInfo.getStackTrace()) {
+            threadDumpDescription.append(System.lineSeparator()).append("\tat ").append(stackTraceElement);
+        }
+        threadDumpDescription.append(System.lineSeparator()).append(System.lineSeparator());
+        return threadDumpDescription.toString();
+    }
+
     private static Properties loadAndTransformProps(String cfgPath) throws IOException {
         Dictionary dict = ConfigurationHandler.read(new FileInputStream(cfgPath));
         Properties props = new Properties();


[jackrabbit-oak] 02/03: return the statuscode as returned by the commands

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a commit to branch OAK-9849
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit ab30c478c3ccf923854f3efc402a11d8215495e5
Author: Joerg Hoh <jh...@adobe.com>
AuthorDate: Fri Jul 22 19:28:12 2022 +0200

    return the statuscode as returned by the commands
---
 oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
index 1b54479dd2..ebcf448405 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
@@ -46,6 +46,8 @@ public final class Main {
             args = copyOfRange(args, 1, args.length);
         }
 
-        command.execute(args);
+        int statuscode = command.execute(args);
+        
+        System.exit(statuscode);
     }
 }


[jackrabbit-oak] 01/03: refactoring: all commands return the final status code (instead using system.exit directly)

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a commit to branch OAK-9849
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit afc5f8c3f353efff1ad925b6194342c6122f109c
Author: Joerg Hoh <jh...@adobe.com>
AuthorDate: Fri Jul 22 19:25:59 2022 +0200

    refactoring: all commands return the final status code (instead using system.exit directly)
---
 .../jackrabbit/oak/benchmark/ElasticBenchmarkRunner.java   |  4 ++--
 .../apache/jackrabbit/oak/run/BenchmarkElasticCommand.java |  4 ++--
 .../jackrabbit/oak/benchmark/LuceneBenchmarkRunner.java    |  3 ++-
 .../apache/jackrabbit/oak/run/BenchmarkLuceneCommand.java  |  4 ++--
 .../jackrabbit/oak/run/ScalabilityLuceneCommand.java       |  4 ++--
 .../oak/scalability/LuceneScalabilityRunner.java           |  4 ++--
 .../jackrabbit/oak/benchmark/SolrBenchmarkRunner.java      |  4 ++--
 .../apache/jackrabbit/oak/run/BenchmarkSolrCommand.java    |  4 ++--
 .../apache/jackrabbit/oak/benchmark/BenchmarkRunner.java   |  6 ++++--
 .../org/apache/jackrabbit/oak/run/BenchmarkCommand.java    |  4 ++--
 .../org/apache/jackrabbit/oak/run/ScalabilityCommand.java  |  4 ++--
 .../jackrabbit/oak/scalability/ScalabilityRunner.java      |  6 ++++--
 .../org/apache/jackrabbit/oak/run/commons/Command.java     |  2 +-
 .../apache/jackrabbit/oak/index/ElasticIndexCommand.java   |  5 +++--
 .../java/org/apache/jackrabbit/oak/console/Console.java    |  4 ++--
 .../java/org/apache/jackrabbit/oak/explorer/Explorer.java  |  5 +++--
 .../jackrabbit/oak/exporter/NodeStateExportCommand.java    |  3 ++-
 .../java/org/apache/jackrabbit/oak/index/IndexCommand.java |  5 +++--
 .../jackrabbit/oak/index/merge/IndexDiffCommand.java       |  9 +++++----
 .../org/apache/jackrabbit/oak/index/merge/IndexMerge.java  |  5 +++--
 .../jackrabbit/oak/plugins/tika/TextExtractorMain.java     |  3 ++-
 .../java/org/apache/jackrabbit/oak/run/BackupCommand.java  |  4 ++--
 .../java/org/apache/jackrabbit/oak/run/CheckCommand.java   |  4 ++--
 .../org/apache/jackrabbit/oak/run/CheckpointsCommand.java  |  6 ++++--
 .../org/apache/jackrabbit/oak/run/ClusterNodesCommand.java |  3 ++-
 .../java/org/apache/jackrabbit/oak/run/CompactCommand.java |  6 +++---
 .../apache/jackrabbit/oak/run/CompositePrepareCommand.java |  3 ++-
 .../java/org/apache/jackrabbit/oak/run/ConsoleCommand.java |  4 ++--
 .../jackrabbit/oak/run/DataStoreCacheUpgradeCommand.java   |  8 +++++---
 .../apache/jackrabbit/oak/run/DataStoreCheckCommand.java   |  4 ++--
 .../org/apache/jackrabbit/oak/run/DataStoreCommand.java    |  7 ++++---
 .../java/org/apache/jackrabbit/oak/run/DebugCommand.java   |  6 +++---
 .../java/org/apache/jackrabbit/oak/run/ExploreCommand.java |  4 ++--
 .../apache/jackrabbit/oak/run/FileStoreDiffCommand.java    |  6 +++---
 .../oak/run/FrozenNodeRefsByScanningCommand.java           |  5 +++--
 .../oak/run/FrozenNodeRefsUsingIndexCommand.java           |  5 +++--
 .../java/org/apache/jackrabbit/oak/run/GarbageCommand.java |  5 +++--
 .../java/org/apache/jackrabbit/oak/run/HelpCommand.java    |  4 ++--
 .../java/org/apache/jackrabbit/oak/run/HistoryCommand.java |  6 +++---
 .../java/org/apache/jackrabbit/oak/run/IOTraceCommand.java |  5 +++--
 .../org/apache/jackrabbit/oak/run/IndexMergeCommand.java   |  4 ++--
 .../org/apache/jackrabbit/oak/run/JsonIndexCommand.java    |  3 ++-
 .../apache/jackrabbit/oak/run/PersistentCacheCommand.java  |  5 +++--
 .../jackrabbit/oak/run/PurgeOldIndexVersionCommand.java    |  3 ++-
 .../org/apache/jackrabbit/oak/run/RDBDDLDumpCommand.java   |  6 +++---
 .../apache/jackrabbit/oak/run/RecoverJournalCommand.java   | 10 +++++-----
 .../org/apache/jackrabbit/oak/run/RecoveryCommand.java     |  7 ++++---
 .../java/org/apache/jackrabbit/oak/run/RepairCommand.java  |  7 ++++---
 .../apache/jackrabbit/oak/run/ResetClusterIdCommand.java   |  3 ++-
 .../java/org/apache/jackrabbit/oak/run/RestoreCommand.java |  6 +++---
 .../org/apache/jackrabbit/oak/run/RevisionsCommand.java    |  4 +++-
 .../org/apache/jackrabbit/oak/run/SearchNodesCommand.java  | 14 +++++++-------
 .../org/apache/jackrabbit/oak/run/SegmentCopyCommand.java  |  6 +++---
 .../java/org/apache/jackrabbit/oak/run/ServerCommand.java  |  5 +++--
 .../org/apache/jackrabbit/oak/run/ThreadDumpCommand.java   |  5 +++--
 .../java/org/apache/jackrabbit/oak/run/TikaCommand.java    |  4 ++--
 .../apache/jackrabbit/oak/run/UnlockUpgradeCommand.java    |  8 +++++---
 .../java/org/apache/jackrabbit/oak/run/UpgradeCommand.java |  3 ++-
 58 files changed, 163 insertions(+), 127 deletions(-)

diff --git a/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/benchmark/ElasticBenchmarkRunner.java b/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/benchmark/ElasticBenchmarkRunner.java
index 555bd2d23d..6dc9398b54 100644
--- a/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/benchmark/ElasticBenchmarkRunner.java
+++ b/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/benchmark/ElasticBenchmarkRunner.java
@@ -25,7 +25,7 @@ public class ElasticBenchmarkRunner extends BenchmarkRunner {
 
     private static ElasticConnection connection;
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         initOptionSet(args);
         statsProvider = options.has(benchmarkOptions.getMetrics()) ? getStatsProvider() : StatisticsProvider.NOOP;
         // Create an Elastic Client Connection here and pass down to all the tests
@@ -80,7 +80,7 @@ public class ElasticBenchmarkRunner extends BenchmarkRunner {
 
                     )
             );
-            BenchmarkRunner.main(args);
+            return BenchmarkRunner.main(args);
         } finally {
             connection.close();
         }
diff --git a/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkElasticCommand.java b/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkElasticCommand.java
index 5672062294..5faea8d789 100644
--- a/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkElasticCommand.java
+++ b/oak-benchmarks-elastic/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkElasticCommand.java
@@ -22,7 +22,7 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 
 public class BenchmarkElasticCommand implements Command {
     @Override
-    public void execute(String... args) throws Exception {
-        ElasticBenchmarkRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return ElasticBenchmarkRunner.main(args);
     }
 }
diff --git a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/benchmark/LuceneBenchmarkRunner.java b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/benchmark/LuceneBenchmarkRunner.java
index fa5a6b39e6..f2cc38558c 100644
--- a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/benchmark/LuceneBenchmarkRunner.java
+++ b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/benchmark/LuceneBenchmarkRunner.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
 
 public class LuceneBenchmarkRunner extends BenchmarkRunner {
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         initOptionSet(args);
         statsProvider = options.has(benchmarkOptions.getMetrics()) ? getStatsProvider() : StatisticsProvider.NOOP;
         BenchmarkRunner.addToBenchMarkList(
@@ -57,5 +57,6 @@ public class LuceneBenchmarkRunner extends BenchmarkRunner {
         );
 
         BenchmarkRunner.main(args);
+        return 0;
     }
 }
diff --git a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkLuceneCommand.java b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkLuceneCommand.java
index 7906415b00..32c1dedd52 100644
--- a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkLuceneCommand.java
+++ b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkLuceneCommand.java
@@ -23,7 +23,7 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 public class BenchmarkLuceneCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        LuceneBenchmarkRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return LuceneBenchmarkRunner.main(args);
     }
 }
diff --git a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityLuceneCommand.java b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityLuceneCommand.java
index 1251dad598..5a0e1ba0e4 100644
--- a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityLuceneCommand.java
+++ b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityLuceneCommand.java
@@ -22,7 +22,7 @@ import org.apache.jackrabbit.oak.scalability.LuceneScalabilityRunner;
 public class ScalabilityLuceneCommand extends ScalabilityCommand {
 
     @Override
-    public void execute(String... args) throws Exception {
-        LuceneScalabilityRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return LuceneScalabilityRunner.main(args);
     }
 }
diff --git a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/scalability/LuceneScalabilityRunner.java b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/scalability/LuceneScalabilityRunner.java
index ed85b4e28c..f3ee6890db 100644
--- a/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/scalability/LuceneScalabilityRunner.java
+++ b/oak-benchmarks-lucene/src/main/java/org/apache/jackrabbit/oak/scalability/LuceneScalabilityRunner.java
@@ -48,7 +48,7 @@ import java.util.Arrays;
 
 public class LuceneScalabilityRunner extends ScalabilityRunner {
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         initOptionSet(args);
         ScalabilityRunner.addToScalabilitySuiteList(
                 Arrays.asList(
@@ -82,7 +82,7 @@ public class LuceneScalabilityRunner extends ScalabilityRunner {
                                 .addBenchmarks(new AggregateNodeSearcher())
                 )
         );
-
+        return 0;
     }
 
 }
diff --git a/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/benchmark/SolrBenchmarkRunner.java b/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/benchmark/SolrBenchmarkRunner.java
index f07a57fe49..5b0415b57e 100644
--- a/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/benchmark/SolrBenchmarkRunner.java
+++ b/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/benchmark/SolrBenchmarkRunner.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
 
 public class SolrBenchmarkRunner extends BenchmarkRunner {
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         initOptionSet(args);
         statsProvider = options.has(benchmarkOptions.getMetrics()) ? getStatsProvider() : StatisticsProvider.NOOP;
 
@@ -35,6 +35,6 @@ public class SolrBenchmarkRunner extends BenchmarkRunner {
                         benchmarkOptions.getWithServer().value(options)))
         );
 
-        BenchmarkRunner.main(args);
+        return BenchmarkRunner.main(args);
     }
 }
diff --git a/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkSolrCommand.java b/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkSolrCommand.java
index e7b39fd4ea..6867c806fa 100644
--- a/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkSolrCommand.java
+++ b/oak-benchmarks-solr/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkSolrCommand.java
@@ -21,7 +21,7 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 
 public class BenchmarkSolrCommand implements Command {
     @Override
-    public void execute(String... args) throws Exception {
-        SolrBenchmarkRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return SolrBenchmarkRunner.main(args);
     }
 }
diff --git a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
index 5edd058902..0829333e4e 100644
--- a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
+++ b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
@@ -79,13 +79,13 @@ public class BenchmarkRunner {
     private static boolean initFlag = false;
 
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
 
         initOptionSet(args);
 
         if (options.has(benchmarkOptions.getHelp())) {
             parser.printHelpOn(System.out);
-            System.exit(0);
+            return 0;
         }
 
         String uri = benchmarkOptions.getMongouri().value(options);
@@ -504,7 +504,9 @@ public class BenchmarkRunner {
             reportMetrics(statsProvider);
         } else {
             System.err.println("Unknown arguments: " + argset);
+            return 1;
         }
+        return 0;
     }
 
     private static void reportMetrics(StatisticsProvider statsProvider) {
diff --git a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java
index 5152b12b57..e90b49ee70 100644
--- a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java
+++ b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/BenchmarkCommand.java
@@ -23,8 +23,8 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 class BenchmarkCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        BenchmarkRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return BenchmarkRunner.main(args);
     }
 
 }
diff --git a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
index f3c65576fc..de51b8e221 100644
--- a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
+++ b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/run/ScalabilityCommand.java
@@ -23,8 +23,8 @@ import org.apache.jackrabbit.oak.scalability.ScalabilityRunner;
 class ScalabilityCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        ScalabilityRunner.main(args);
+    public int execute(String... args) throws Exception {
+        return ScalabilityRunner.main(args);
     }
 
 }
diff --git a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java
index 0c66de41c2..e8dc7f5463 100644
--- a/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java
+++ b/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/scalability/ScalabilityRunner.java
@@ -56,13 +56,13 @@ public class ScalabilityRunner {
     protected static OptionSet options;
     private static boolean initFlag = false;
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         initOptionSet(args);
         OptionSet options = parser.parse(args);
 
         if (options.has(scalabilityOptions.getHelp())) {
             parser.printHelpOn(System.out);
-            System.exit(0);
+            return 0;
         }
 
         int cacheSize = scalabilityOptions.getCache().value(options);
@@ -187,7 +187,9 @@ public class ScalabilityRunner {
             }
         } else {
             System.err.println("Unknown arguments: " + argset);
+            return 1;
         }
+        return 0;
     }
 
     protected static void addToScalabilitySuiteList(List<ScalabilitySuite> suites) {
diff --git a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/commons/Command.java b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/commons/Command.java
index 16385f6303..f7be83b137 100644
--- a/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/commons/Command.java
+++ b/oak-run-commons/src/main/java/org/apache/jackrabbit/oak/run/commons/Command.java
@@ -19,6 +19,6 @@ package org.apache.jackrabbit.oak.run.commons;
 
 public interface Command {
 
-    void execute(String... args) throws Exception;
+    int execute(String... args) throws Exception;
 
 }
diff --git a/oak-run-elastic/src/main/java/org/apache/jackrabbit/oak/index/ElasticIndexCommand.java b/oak-run-elastic/src/main/java/org/apache/jackrabbit/oak/index/ElasticIndexCommand.java
index 682e57e945..1bbc4fb1bf 100644
--- a/oak-run-elastic/src/main/java/org/apache/jackrabbit/oak/index/ElasticIndexCommand.java
+++ b/oak-run-elastic/src/main/java/org/apache/jackrabbit/oak/index/ElasticIndexCommand.java
@@ -74,7 +74,7 @@ public class ElasticIndexCommand implements Command {
 
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         opts = new Options();
@@ -123,8 +123,9 @@ public class ElasticIndexCommand implements Command {
 
         if (!success) {
             //Needed for changes after OAK-6409
-            System.exit(1);
+            return 1;
         }
+        return 0;
     }
 
     private void execute(NodeStoreFixture fixture, ElasticIndexOptions indexOpts, Closer closer)
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java
index eb5f4ee076..1534b5dbf7 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/console/Console.java
@@ -36,7 +36,7 @@ import org.codehaus.groovy.tools.shell.util.Preferences;
  */
 public class Console {
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         OptionParser parser = new OptionParser();
 
         OptionSpec quiet = parser.accepts("quiet", "be less chatty");
@@ -75,6 +75,6 @@ public class Console {
             }
         }
 
-        System.exit(code);
+        return code;
     }
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java
index 7388258ca8..30e27468ad 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/explorer/Explorer.java
@@ -53,7 +53,7 @@ public class Explorer {
         }
     }
 
-    public static void main(String[] args) throws IOException {
+    public static int main(String[] args) throws IOException {
         OptionParser parser = new OptionParser();
         OptionSpec skipSizeCheck = parser.accepts("skip-size-check", "Don't compute the size of the records");
         OptionSpec<String> nonOptions = parser.nonOptions("path to repository").ofType(String.class);
@@ -61,7 +61,7 @@ public class Explorer {
 
         if (options.valuesOf(nonOptions).isEmpty()) {
             parser.printHelpOn(System.err);
-            System.exit(1);
+            return 1;
         }
 
         String path = options.valuesOf(nonOptions).get(0);
@@ -73,6 +73,7 @@ public class Explorer {
             backend = new SegmentTarExplorerBackend(path);
         }
         new Explorer(path, backend, options.has(skipSizeCheck));
+        return 0;
     }
 
     private final ExplorerBackend backend;
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateExportCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateExportCommand.java
index 7e9f614691..8c56043994 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateExportCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/exporter/NodeStateExportCommand.java
@@ -35,7 +35,7 @@ public class NodeStateExportCommand implements Command {
     private final String summary = "Exports NodeState as json";
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Stopwatch w = Stopwatch.createStarted();
         OptionParser parser = new OptionParser();
 
@@ -69,5 +69,6 @@ public class NodeStateExportCommand implements Command {
                     eo.getPath(), dir.getAbsolutePath(), w);
 
         }
+        return 0;
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java
index 20a1ae0958..0578bde1f5 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/IndexCommand.java
@@ -83,7 +83,7 @@ public class IndexCommand implements Command {
     }
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         opts = new Options();
@@ -145,8 +145,9 @@ public class IndexCommand implements Command {
         }
 
         if (!success) {
-            System.exit(1);
+            return 1;
         }
+        return 0;
     }
 
     public static void setDisableExitOnError(boolean disableExitOnError) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDiffCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDiffCommand.java
index eb56427428..82912df0df 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDiffCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDiffCommand.java
@@ -29,7 +29,7 @@ import joptsimple.OptionSpec;
 public class IndexDiffCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<String> customDirOption = parser
                 .accepts("custom", "Path to index definition files (.json). " +
@@ -79,7 +79,7 @@ public class IndexDiffCommand implements Command {
                 compareDirectory.isEmpty() &&
                 extractFile.isEmpty())) {
             parser.printHelpOn(System.out);
-            return;
+            return 1;
         }
         if (!customDir.isEmpty()) {
             System.out.println("Listing differences between out-of-the-box and customized indexes " +
@@ -90,7 +90,7 @@ public class IndexDiffCommand implements Command {
             String mergeAdd = mergeAddFileOption.value(options);
             if (mergeAdd.isEmpty()) {
                 parser.printHelpOn(System.out);
-                return;
+                return 1;
             }
             if (targetDirectory.isEmpty()) {
                 System.out.println("Merging indexes " +
@@ -118,7 +118,7 @@ public class IndexDiffCommand implements Command {
             } else {
                 if (index1.isEmpty() || index2.isEmpty()) {
                     parser.printHelpOn(System.out);
-                    return;
+                    return 1;
                 }
                 System.out.println("Comparing indexes " + index1 + " and " + index2 +
                         " for directory \"" +
@@ -138,6 +138,7 @@ public class IndexDiffCommand implements Command {
                 IndexDiff.extractAll(extractFile, targetDirectory);
             }
         }
+        return 0;
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexMerge.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexMerge.java
index 7ca4859678..c485b5ed01 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexMerge.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexMerge.java
@@ -96,7 +96,7 @@ public class IndexMerge {
      *
      * @param args the command line arguments
      */
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<Void> quietOption = parser.accepts("quiet", "be less chatty");
         OptionSpec<String> indexDirectory = parser.accepts("indexDir", "Index directory").
@@ -162,8 +162,9 @@ public class IndexMerge {
             executorService.shutdown();
         }
         if (!success) {
-            System.exit(1);
+            return 1;
         }
+        return 0;
     }
 
     private void storeIndex(NodeStore ns, String newIndexName, JsonObject indexDef) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/tika/TextExtractorMain.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/tika/TextExtractorMain.java
index 706e54dd7c..4e1134b7a6 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/tika/TextExtractorMain.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/tika/TextExtractorMain.java
@@ -46,7 +46,7 @@ public class TextExtractorMain {
     private TextExtractorMain() {
     }
 
-    public static void main(String[] args) throws Exception {
+    public static int main(String[] args) throws Exception {
         OptionParser parser = new OptionParser();
 
         Options opts = new Options();
@@ -175,5 +175,6 @@ public class TextExtractorMain {
                 writer.close();
             }
         }
+        return 0;
     }
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java
index 7e897fe9da..96cb9aa084 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/BackupCommand.java
@@ -27,7 +27,7 @@ import org.apache.jackrabbit.oak.segment.tool.Backup;
 class BackupCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSet options = parser.parse(args);
 
@@ -44,7 +44,7 @@ class BackupCommand implements Command {
             .withTarget(target)
             .build()
             .run();
-        System.exit(statusCode);
+       return statusCode;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java
index 7a0815679e..0a9359a91c 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckCommand.java
@@ -32,7 +32,7 @@ import org.apache.jackrabbit.oak.segment.tool.Check;
 class CheckCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<Boolean> mmapArg = parser.accepts("mmap", "use memory mapping for the file store (default: true)")
             .withOptionalArg()
@@ -94,7 +94,7 @@ class CheckCommand implements Command {
             builder.withRevisionsCount(options.valueOf(last) != null ? last.value(options) : 1);
         }
 
-        System.exit(builder.build().run());
+        return builder.build().run();
     }
 
     private void printUsageAndExit(OptionParser parser, String... messages) throws IOException {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java
index 792dd054ed..b5c8caa531 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CheckpointsCommand.java
@@ -33,7 +33,7 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 class CheckpointsCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
 
         CheckpointsOptions options = new CheckpointsOptions("checkpoints {<path>|<mongo-uri>|<jdbc-uri>} [list|rm-all|rm-unreferenced|rm <checkpoint>|info <checkpoint>|set <checkpoint> <name> [<value>]] [--segment]").parse(args);;
         if (options.isHelp()) {
@@ -170,8 +170,10 @@ class CheckpointsCommand implements Command {
             closer.close();
         }
         if (!success) {
-            System.exit(1);
+            return 1;
         }
+        return 0;
+        
     }
 
     private static void failWith(String message) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ClusterNodesCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ClusterNodesCommand.java
index d93eafe100..60905a431e 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ClusterNodesCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ClusterNodesCommand.java
@@ -41,7 +41,7 @@ import joptsimple.OptionSpec;
 class ClusterNodesCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Closer closer = Utils.createCloserWithShutdownHook();
         try {
             String h = "clusternodes mongodb://host:port/database|jdbc:...";
@@ -83,6 +83,7 @@ class ClusterNodesCommand implements Command {
         } finally {
             closer.close();
         }
+        return 0;
     }
 
     private static void print(List<ClusterNodeInfoDocument> docs, boolean verbose) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java
index 77f9dcda04..23c97cd171 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompactCommand.java
@@ -37,7 +37,7 @@ class CompactCommand implements Command {
     }
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<String> directoryArg = parser.nonOptions(
                 "Path/URI to TAR/remote segment store (required)").ofType(String.class);
@@ -82,7 +82,7 @@ class CompactCommand implements Command {
         if (path == null) {
             System.err.println("Compact a file store. Usage: compact [path] <options>");
             parser.printHelpOn(System.err);
-            System.exit(-1);
+            return -1;
         }
 
         int code = 0;
@@ -141,7 +141,7 @@ class CompactCommand implements Command {
                     .run();
         }
 
-        System.exit(code);
+        return code;
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompositePrepareCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompositePrepareCommand.java
index 5cce6c4f34..66102e9515 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompositePrepareCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/CompositePrepareCommand.java
@@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
 public class CompositePrepareCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         OptionSpec<?> help = parser
@@ -77,6 +77,7 @@ public class CompositePrepareCommand implements Command {
         } finally {
             fs.close();
         }
+        return 0;
     }
 
     public static class OakResourceTransformer {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java
index 052341de3e..2bb1e8a259 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ConsoleCommand.java
@@ -23,8 +23,8 @@ import org.apache.jackrabbit.oak.console.Console;
 class ConsoleCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        Console.main(args);
+    public int execute(String... args) throws Exception {
+        return Console.main(args);
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCacheUpgradeCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCacheUpgradeCommand.java
index 3755064877..a835a2d0cd 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCacheUpgradeCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCacheUpgradeCommand.java
@@ -32,7 +32,7 @@ import static java.util.Arrays.asList;
  */
 public class DataStoreCacheUpgradeCommand implements Command {
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         try {
@@ -56,12 +56,12 @@ public class DataStoreCacheUpgradeCommand implements Command {
             } catch (Exception e) {
                 System.err.println(e);
                 parser.printHelpOn(System.err);
-                return;
+                return 1;
             }
 
             if (options.has(help)) {
                 parser.printHelpOn(System.out);
-                return;
+                return 1;
             }
 
             File homeDir = options.valueOf(homeDirOption);
@@ -77,6 +77,8 @@ public class DataStoreCacheUpgradeCommand implements Command {
         } catch (Exception e) {
             e.printStackTrace();
             System.err.println("Error upgrading cache");
+            return 1;
         }
+        return 0;
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCheckCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCheckCommand.java
index 726fe143e9..ff2a797422 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCheckCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCheckCommand.java
@@ -110,8 +110,8 @@ public class DataStoreCheckCommand implements Command {
     };
 
     @Override
-    public void execute(String... args) throws Exception {
-        System.exit(checkDataStore(args));
+    public int execute(String... args) throws Exception {
+        return checkDataStore(args);
     }
 
     static int checkDataStore(String... args) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCommand.java
index a839aa53b2..316b428099 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DataStoreCommand.java
@@ -122,7 +122,7 @@ public class DataStoreCommand implements Command {
     };
 
 
-    @Override public void execute(String... args) throws Exception {
+    @Override public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         opts = new Options();
@@ -152,7 +152,7 @@ public class DataStoreCommand implements Command {
             log.info("Node Store fixture created and registered");
 
             if (!checkParameters(dataStoreOpts, opts, fixture, parser)) {
-                return;
+                return 1;
             }
             execute(fixture, dataStoreOpts, opts, closer);
             success = true;
@@ -164,8 +164,9 @@ public class DataStoreCommand implements Command {
         }
 
         if (!success) {
-            System.exit(1);
+            return 1;
         }
+        return 0;
     }
 
     private static boolean checkParameters(DataStoreOptions dataStoreOpts, Options opts, NodeStoreFixture fixture,
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java
index dbf63329db..722c736c13 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/DebugCommand.java
@@ -32,17 +32,17 @@ import org.apache.jackrabbit.oak.segment.tool.DebugTars;
 class DebugCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<String> nonOptions = parser.nonOptions().ofType(String.class);
         OptionSet options = parser.parse(args);
 
         if (options.valuesOf(nonOptions).isEmpty()) {
             System.err.println("usage: debug <path> [id...]");
-            System.exit(1);
+            return 1;
         }
 
-        System.exit(debug(options.valuesOf(nonOptions)));
+        return debug(options.valuesOf(nonOptions));
     }
 
     private static int debug(List<String> args) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java
index e4d60dd46c..5b533d5d36 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ExploreCommand.java
@@ -23,8 +23,8 @@ import org.apache.jackrabbit.oak.explorer.Explorer;
 class ExploreCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        Explorer.main(args);
+    public int  execute(String... args) throws Exception {
+        return Explorer.main(args);
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
index 5b0871b216..ae5792d8d4 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FileStoreDiffCommand.java
@@ -31,7 +31,7 @@ import org.apache.jackrabbit.oak.segment.tool.Revisions;
 class FileStoreDiffCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<?> help = parser.acceptsAll(asList("h", "?", "help"), "show help").forHelp();
         OptionSpec<File> storeO = parser.nonOptions("Path to segment store (required)").ofType(File.class);
@@ -52,7 +52,7 @@ class FileStoreDiffCommand implements Command {
 
         if (store == null) {
             parser.printHelpOn(System.out);
-            System.exit(1);
+            return 1;
         }
 
         File out = outO.value(options);
@@ -81,7 +81,7 @@ class FileStoreDiffCommand implements Command {
                 .build()
                 .run();
         }
-        System.exit(statusCode);
+        return statusCode;
     }
 
     private File defaultOutFile() {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsByScanningCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsByScanningCommand.java
index e2cdea4ed0..323f664f10 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsByScanningCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsByScanningCommand.java
@@ -96,7 +96,7 @@ public class FrozenNodeRefsByScanningCommand implements Command {
     private final String summary = "Scans repository and lists all references to nt:frozenNode";
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         Options opts = new Options();
@@ -117,10 +117,11 @@ public class FrozenNodeRefsByScanningCommand implements Command {
         int count = uuidscan(userOption, passwordOption, options, nodeStoreFixture);
         if (count > 0) {
             System.err.println("FAILURE: " + count + " Reference(s) (in any uuid formatted property value) to nt:frozenNode found.");
-            System.exit(1);
+            return 1;
         } else {
             System.out.println("SUCCESS: No references (in any uuid formatted property value) to nt:frozenNode found.");
         }
+        return 0;
     }
 
     /**
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsUsingIndexCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsUsingIndexCommand.java
index 7f0dad2a42..7959929536 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsUsingIndexCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/FrozenNodeRefsUsingIndexCommand.java
@@ -50,16 +50,17 @@ public class FrozenNodeRefsUsingIndexCommand implements Command {
     public static final String NAME = "frozennoderefsusingindex";
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         String help = NAME + " {<path>|<mongo-uri>|<jdbc-uri>} [options]";
         Utils.NodeStoreOptions nopts = new Utils.NodeStoreOptions(help).parse(args);
         int count = countNtFrozenNodeReferences(nopts);
         if (count > 0) {
             System.err.println("FAILURE: " + count + " Reference(s) (in /oak:index/references) to nt:frozenNode found.");
-            System.exit(1);
+            return 1;
         } else {
             System.out.println("SUCCESS: No references (in /oak:index/references) to nt:frozenNode found.");
         }
+        return 0;
     }
 
     /**
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java
index 4787f65676..39264674c5 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/GarbageCommand.java
@@ -26,14 +26,14 @@ import org.apache.jackrabbit.oak.spi.state.NodeStore;
 class GarbageCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Closer closer = Utils.createCloserWithShutdownHook();
         String h = "garbage mongodb://host:port/database | jdbc:...";
         try {
             NodeStore store = Utils.bootstrapNodeStore(args, closer, h);
             if (!(store instanceof DocumentNodeStore)) {
                 System.err.println("Garbage mode only available for DocumentNodeStore");
-                System.exit(1);
+                return 1;
             }
             DocumentNodeStore dns = (DocumentNodeStore) store;
 
@@ -43,6 +43,7 @@ class GarbageCommand implements Command {
         } finally {
             closer.close();
         }
+        return 0;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
index ef14133599..d899eb13ab 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HelpCommand.java
@@ -25,10 +25,10 @@ import static org.apache.jackrabbit.oak.run.AvailableModes.MODES;
 class HelpCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         System.err.print("Available run modes: ");
         System.err.println(Joiner.on(", ").join(MODES.getModes()));
-        System.exit(1);
+        return 1;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java
index d70c56db04..91fc09b875 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/HistoryCommand.java
@@ -30,7 +30,7 @@ import org.apache.jackrabbit.oak.segment.tool.History;
 class HistoryCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<File> directoryArg = parser.nonOptions(
                 "Path to segment store (required)").ofType(File.class);
@@ -49,7 +49,7 @@ class HistoryCommand implements Command {
         if (directory == null) {
             System.err.println("Trace the history of a path. Usage: history [File] <options>");
             parser.printHelpOn(System.err);
-            System.exit(-1);
+            return -1;
         }
 
         String path = pathArg.value(options);
@@ -64,7 +64,7 @@ class HistoryCommand implements Command {
             .withDepth(depth)
             .build()
             .run();
-        System.exit(returnCode);
+        return returnCode;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IOTraceCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IOTraceCommand.java
index 09716e57c6..1886fce476 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IOTraceCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IOTraceCommand.java
@@ -60,7 +60,7 @@ class IOTraceCommand implements Command {
     public static final String NAME = "iotrace";
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser optionParser = new OptionParser();
         ArgumentAcceptingOptionSpec<Traces> traceOption = optionParser
                 .accepts("trace", "type of the traversal. Either of " + Arrays.toString(Traces.values()))
@@ -151,8 +151,9 @@ class IOTraceCommand implements Command {
             trace.collectIOTrace(segmentStore, mmap, segmentCache, output);
         } catch (OptionException e) {
             printUsage(optionParser, System.err, e.getMessage());
-            System.exit(1);
+            return 1;
         }
+        return 0;
     }
 
     private static void printUsage(
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IndexMergeCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IndexMergeCommand.java
index 841667c5a5..d46d211998 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IndexMergeCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/IndexMergeCommand.java
@@ -24,8 +24,8 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 public class IndexMergeCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        new IndexMerge().execute(args);
+    public int execute(String... args) throws Exception {
+        return new IndexMerge().execute(args);
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/JsonIndexCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/JsonIndexCommand.java
index 0b6097bb9c..efc484909b 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/JsonIndexCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/JsonIndexCommand.java
@@ -85,7 +85,7 @@ public class JsonIndexCommand implements Command {
     private final Map<String, Object> data = new HashMap<String, Object>();
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<String> scriptOption = parser
                 .accepts("script", "Path to Script").withOptionalArg()
@@ -114,6 +114,7 @@ public class JsonIndexCommand implements Command {
             nodeStoreFixture.close();
             reader.close();
         }
+        return 0;
     }
 
     private LineNumberReader openScriptReader(String script)
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PersistentCacheCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PersistentCacheCommand.java
index a82da756f3..71ff817a51 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PersistentCacheCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PersistentCacheCommand.java
@@ -41,7 +41,7 @@ public class PersistentCacheCommand implements Command {
 
     @SuppressWarnings("unchecked")
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<String> pathSpec = parser.accepts("path", 
                 "only list entries starting with this path prefix").
@@ -77,7 +77,7 @@ public class PersistentCacheCommand implements Command {
                     "create table cache as select * from csvread('cache.csv', null, 'fieldDelimiter=')");
             System.out.println();
             parser.printHelpOn(System.out);
-            return;
+            return 1;
         }
         String path = pathSpec.value(options);
         String revision = revisionSpec.value(options);
@@ -93,6 +93,7 @@ public class PersistentCacheCommand implements Command {
             dump(write, path, revision, map, fileName, values, raw);
         }      
         write.flush();
+        return 0;
     }
     
     static void dump(PrintWriter write, String path, String revision, 
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PurgeOldIndexVersionCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PurgeOldIndexVersionCommand.java
index 160db17284..adc15eebe7 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PurgeOldIndexVersionCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/PurgeOldIndexVersionCommand.java
@@ -41,7 +41,7 @@ public class PurgeOldIndexVersionCommand implements Command {
     private final static String DEFAULT_INDEX_PATH = "/oak:index";
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Options opts = parseCommandLineParams(args);
         try (NodeStoreFixture fixture = NodeStoreFixtureProvider.create(opts)) {
             if (!opts.getCommonOpts().isReadWrite()) {
@@ -49,6 +49,7 @@ public class PurgeOldIndexVersionCommand implements Command {
             }
             new PurgeOldIndexVersion().execute(fixture.getStore(), opts.getCommonOpts().isReadWrite(), threshold, indexPaths);
         }
+        return 0;
     }
 
     private Options parseCommandLineParams(String... args) throws Exception {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RDBDDLDumpCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RDBDDLDumpCommand.java
index bd6018b094..66f3e0afce 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RDBDDLDumpCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RDBDDLDumpCommand.java
@@ -29,7 +29,7 @@ import joptsimple.OptionSpec;
 public class RDBDDLDumpCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<Void> helpOption = parser.accepts("help", "show help").forHelp();
         OptionSpec<String> dbOption = parser.accepts("db", "Database type: one of " + RDBHelper.getSupportedDatabases())
@@ -51,14 +51,14 @@ public class RDBDDLDumpCommand implements Command {
                 Integer upgrade = upgradeSchemaOption.value(options);
                 RDBHelper.dump(db, initial, upgrade);
             }
-            System.exit(0);
+            return 0;
         } catch (joptsimple.OptionException ex) {
             System.err.println(ex.getLocalizedMessage());
             System.err.println(Arrays.toString(args));
             System.err.println();
             System.err.println("Options:");
             parser.printHelpOn(System.err);
-            System.exit(2);
+            return 2;
         }
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoverJournalCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoverJournalCommand.java
index f6eeaa4cdd..50922ea6d5 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoverJournalCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoverJournalCommand.java
@@ -32,7 +32,7 @@ import org.apache.jackrabbit.oak.segment.tool.RecoverJournal;
 class RecoverJournalCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser options = new OptionParser();
         OptionSpec<?> help = options.acceptsAll(asList("h", "help"), "Prints help and exits");
         OptionSpec<File> dir = options.nonOptions()
@@ -42,17 +42,17 @@ class RecoverJournalCommand implements Command {
 
         if (parsed.has(help)) {
             options.printHelpOn(System.out);
-            System.exit(0);
+            return 0;
         }
 
         if (parsed.valuesOf(dir).size() == 0) {
             System.err.println("Segment Store path not specified");
-            System.exit(1);
+            return 1;
         }
 
         if (parsed.valuesOf(dir).size() > 1) {
             System.err.println("Too many Segment Store paths specified");
-            System.exit(1);
+            return 1;
         }
 
         int code = RecoverJournal.builder()
@@ -61,7 +61,7 @@ class RecoverJournalCommand implements Command {
             .withErr(System.err)
             .build()
             .run();
-        System.exit(code);
+        return code;
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
index 32978cd05d..40329380c8 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RecoveryCommand.java
@@ -44,7 +44,7 @@ class RecoveryCommand implements Command {
     MapFactory oldf = MapFactory.getInstance();
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Closer closer = Utils.createCloserWithShutdownHook();
         MapDBMapFactory mdbmf = new MapDBMapFactory();
         closer.register(mdbmf);
@@ -96,7 +96,7 @@ class RecoveryCommand implements Command {
             if (agent == null || seeker == null) {
                 System.err.println("Recovery only available for MongoDocumentStore and RDBDocumentStore (this: "
                         + ds.getClass().getName() + ")");
-                System.exit(1);
+                return 1;
             }
 
             if (builder.getClusterId() == 0) {
@@ -114,7 +114,7 @@ class RecoveryCommand implements Command {
                 catch (Throwable e) {
                     e.printStackTrace(System.err);
                 }
-                System.exit(1);
+                return 1;
             }
 
             Iterable<NodeDocument> docs = seeker.getCandidates(0);
@@ -129,5 +129,6 @@ class RecoveryCommand implements Command {
             closer.close();
             MapFactory.setInstance(oldf);
         }
+        return 0;
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
index c84ed47eee..6446d1473e 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RepairCommand.java
@@ -27,19 +27,19 @@ import org.apache.jackrabbit.oak.spi.state.NodeStore;
 class RepairCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Closer closer = Utils.createCloserWithShutdownHook();
         String h = "repair mongodb://host:port/database path";
         try {
             NodeStore store = Utils.bootstrapNodeStore(args, closer, h);
             if (!(store instanceof DocumentNodeStore)) {
                 System.err.println("Repair only available for DocumentNodeStore");
-                System.exit(1);
+                return 1;
             }
             DocumentNodeStore dns = (DocumentNodeStore) store;
             if (!(dns.getDocumentStore() instanceof MongoDocumentStore)) {
                 System.err.println("Repair only available for MongoDocumentStore");
-                System.exit(1);
+                return 1;
             }
             MongoDocumentStore docStore = (MongoDocumentStore) dns.getDocumentStore();
 
@@ -50,6 +50,7 @@ class RepairCommand implements Command {
         } finally {
             closer.close();
         }
+        return 0;
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ResetClusterIdCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ResetClusterIdCommand.java
index 4c4ee993c0..436e2b5256 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ResetClusterIdCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ResetClusterIdCommand.java
@@ -72,7 +72,7 @@ class ResetClusterIdCommand implements Command {
     }
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         String help = "resetclusterid {<path>|<mongo-uri>|<jdbc-uri>}";
         Utils.NodeStoreOptions opts = new Utils.NodeStoreOptions(help).parse(args);
 
@@ -85,5 +85,6 @@ class ResetClusterIdCommand implements Command {
         } finally {
             closer.close();
         }
+        return 0;
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
index 36bec470d1..67bd6e30e4 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RestoreCommand.java
@@ -27,13 +27,13 @@ import org.apache.jackrabbit.oak.segment.tool.Restore;
 class RestoreCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSet options = parser.parse(args);
 
         if (options.nonOptionArguments().size() < 2) {
             System.err.println("This command requires a target and a source folder");
-            System.exit(1);
+            return 1;
         }
 
         File target = new File(options.nonOptionArguments().get(0).toString());
@@ -44,7 +44,7 @@ class RestoreCommand implements Command {
             .withTarget(target)
             .build()
             .run();
-        System.exit(statusCode);
+        return statusCode;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RevisionsCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RevisionsCommand.java
index 21e5aff706..f39795d622 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RevisionsCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/RevisionsCommand.java
@@ -165,7 +165,7 @@ public class RevisionsCommand implements Command {
     }
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         Closer closer = Closer.create();
         try {
             RevisionsOptions options = new RevisionsOptions(USAGE).parse(args);
@@ -182,6 +182,7 @@ public class RevisionsCommand implements Command {
                 sweep(options, closer);
             } else {
                 System.err.println("unknown revisions command: " + subCmd);
+                return 1;
             }
         } catch (Throwable e) {
             LOG.error("Command failed", e);
@@ -189,6 +190,7 @@ public class RevisionsCommand implements Command {
         } finally {
             closer.close();
         }
+        return 0;
     }
 
     private void setupLoggers(boolean verbose) {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SearchNodesCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SearchNodesCommand.java
index da3bd2514b..51de3b3e63 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SearchNodesCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SearchNodesCommand.java
@@ -34,7 +34,7 @@ import org.apache.jackrabbit.oak.segment.tool.SearchNodes.Output;
 class SearchNodesCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser options = new OptionParser();
         OptionSpec<String> property = options.acceptsAll(asList("p", "property"), "Matches a property name")
             .withRequiredArg()
@@ -57,17 +57,17 @@ class SearchNodesCommand implements Command {
 
         if (parsed.has(help)) {
             options.printHelpOn(System.out);
-            System.exit(0);
+            return 0;
         }
 
         if (parsed.valuesOf(dir).size() == 0) {
             System.err.println("Segment Store path not specified");
-            System.exit(1);
+            return 1;
         }
 
         if (parsed.valuesOf(dir).size() > 1) {
             System.err.println("Too many Segment Store paths specified");
-            System.exit(1);
+            return 1;
         }
 
         Builder builder = SearchNodes.builder()
@@ -87,7 +87,7 @@ class SearchNodesCommand implements Command {
                     break;
                 default:
                     System.err.printf("Unrecognized output: %s\n", v);
-                    System.exit(1);
+                    return 1;
             }
         }
 
@@ -104,13 +104,13 @@ class SearchNodesCommand implements Command {
 
             if (parts.length != 2) {
                 System.err.println("Invalid property value specified: " + v);
-                System.exit(1);
+                return 1;
             }
 
             builder.withValue(parts[0], parts[1]);
         }
 
-        System.exit(builder.build().run());
+        return builder.build().run();
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentCopyCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentCopyCommand.java
index b2b9219d41..d0cdf733ec 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentCopyCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/SegmentCopyCommand.java
@@ -31,7 +31,7 @@ import joptsimple.OptionSet;
 class SegmentCopyCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         OptionSpec<Integer> last = parser.accepts("last", "define the number of revisions to be copied (default: 1)")
@@ -69,7 +69,7 @@ class SegmentCopyCommand implements Command {
                 builder.withRevisionsCount(last.value(options) != null ? last.value(options) : 1);
             }
 
-            System.exit(builder.build().run());
+            return builder.build().run();
         } else {
             SegmentCopy.Builder builder = SegmentCopy.builder()
                     .withSource(source)
@@ -86,7 +86,7 @@ class SegmentCopyCommand implements Command {
                 builder.withFlat(flat.value(options));
             }
 
-            System.exit(builder.build().run());
+            return builder.build().run();
         }
     }
 
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
index 1926d9a621..4458d7022f 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ServerCommand.java
@@ -56,7 +56,7 @@ class ServerCommand implements Command {
     }
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
 
         OptionSpec<Integer> cache = parser.accepts("cache", "cache size (MB)").withRequiredArg().ofType(Integer.class).defaultsTo(100);
@@ -84,7 +84,7 @@ class ServerCommand implements Command {
 
         if (options.has(help)) {
             parser.printHelpOn(System.out);
-            System.exit(0);
+            return 0;
         }
 
         OakFixture oakFixture;
@@ -131,6 +131,7 @@ class ServerCommand implements Command {
         }
 
         startOakServer(oakFixture, uri, cIds);
+        return 0;
     }
 
 }
\ No newline at end of file
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
index 4b97b6b4a1..4e560234cb 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
@@ -55,7 +55,7 @@ public class ThreadDumpCommand implements Command {
 
     @SuppressWarnings("unchecked")
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         OptionSpec<Void> convertSpec = parser.accepts("convert",
                 "convert the thread dumps to the standard format");
@@ -85,7 +85,7 @@ public class ThreadDumpCommand implements Command {
             System.out.println("Mode: " + THREADDUMP);
             System.out.println();
             parser.printHelpOn(System.out);
-            return;
+            return 1;
         }
         boolean convert = options.has(convertSpec);
         boolean filter = options.has(filterSpec);
@@ -132,6 +132,7 @@ public class ThreadDumpCommand implements Command {
                 Profiler.main(list.toArray(new String[0]));
             }
         }
+        return 0;
     }
 
     private static File combineAndExpandFiles(File file) throws IOException {
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/TikaCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/TikaCommand.java
index 17d9bb1a9c..5263348263 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/TikaCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/TikaCommand.java
@@ -23,8 +23,8 @@ import org.apache.jackrabbit.oak.plugins.tika.TextExtractorMain;
 class TikaCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
-        TextExtractorMain.main(args);
+    public int execute(String... args) throws Exception {
+        return TextExtractorMain.main(args);
     }
 
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UnlockUpgradeCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UnlockUpgradeCommand.java
index a266a84fd7..6dd57cfa83 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UnlockUpgradeCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UnlockUpgradeCommand.java
@@ -49,7 +49,7 @@ import static org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore.VERSI
 class UnlockUpgradeCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         OptionParser parser = new OptionParser();
         // RDB specific options
         OptionSpec<String> rdbjdbcuser = parser.accepts("rdbjdbcuser", "RDB JDBC user").withOptionalArg().defaultsTo("");
@@ -63,12 +63,12 @@ class UnlockUpgradeCommand implements Command {
 
         if (options.has(help)) {
             parser.printHelpOn(System.out);
-            return;
+            return 0;
         }
 
         if (nonOptions.isEmpty()) {
             parser.printHelpOn(System.err);
-            return;
+            return 0;
         }
 
         DocumentStore store = null;
@@ -97,10 +97,12 @@ class UnlockUpgradeCommand implements Command {
             }
         } catch (DocumentStoreException e) {
             System.err.println(e.getMessage());
+            return 1;
         } finally {
             if (store != null) {
                 store.dispose();
             }
         }
+        return 0;
     }
 }
diff --git a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UpgradeCommand.java b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UpgradeCommand.java
index caa5242713..6310b39083 100644
--- a/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UpgradeCommand.java
+++ b/oak-run/src/main/java/org/apache/jackrabbit/oak/run/UpgradeCommand.java
@@ -22,8 +22,9 @@ import org.apache.jackrabbit.oak.run.commons.Command;
 class UpgradeCommand implements Command {
 
     @Override
-    public void execute(String... args) throws Exception {
+    public int execute(String... args) throws Exception {
         System.out.println("This command was moved to the oak-upgrade module");
+        return 1;
     }
 
 }