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

shirshanka pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-gobblin.git


The following commit(s) were added to refs/heads/master by this push:
     new 06b9159  [GOBBLIN-1267] Gobblin cli: Add a quickApp called oneShot to 
run a single command in standalone and MR mode
06b9159 is described below

commit 06b9159e034ca2a7e1b72b1a306ae24a2fe6485e
Author: Shirshanka Das <[email protected]>
AuthorDate: Mon Sep 21 23:06:42 2020 -0700

    [GOBBLIN-1267] Gobblin cli: Add a quickApp called oneShot to run a single 
command in standalone and MR mode
    
    Closes #3058 from shirshanka/cli-improve
---
 bin/gobblin.sh                                     |  8 +-
 gobblin-docs/user-guide/Gobblin-CLI.md             | 41 ++++++++-
 .../gobblin/example/generic/OneShotRunner.java     | 99 ++++++++++++++++++++++
 .../apache/gobblin/example/TestOneShotRunner.java  | 43 ++++++++++
 gobblin-example/src/test/resources/appConf.conf    |  1 +
 gobblin-example/src/test/resources/baseConf.conf   |  2 +
 .../gobblin/runtime/embedded/EmbeddedGobblin.java  | 28 +++---
 .../runtime/mapreduce/CliMRJobLauncher.java        |  8 +-
 .../gobblin/runtime/mapreduce/MRJobLauncher.java   |  6 ++
 .../org/apache/gobblin/runtime/cli/GobblinCli.java |  5 +-
 10 files changed, 222 insertions(+), 19 deletions(-)

diff --git a/bin/gobblin.sh b/bin/gobblin.sh
index 968106a..83af03e 100755
--- a/bin/gobblin.sh
+++ b/bin/gobblin.sh
@@ -398,12 +398,13 @@ function start() {
             echo "$GOBBLIN_CLASSPATH"
         else
             #prints the command
+            GOBBLIN_COMMAND="$JAVA_HOME/bin/java $GC_OPTS $JVM_OPTS 
$LOG4J_OPTS -cp $GOBBLIN_CLASSPATH $CLI_CLASS $CMD_PARAMS"
             if [[ $VERBOSE -eq 1 ]]; then
-                echo "Running command: $JAVA_HOME/bin/java $GC_OPTS $JVM_OPTS 
-cp $GOBBLIN_CLASSPATH $CLI_CLASS $CMD_PARAMS";
+                echo "Running command: $GOBBLIN_COMMAND";
             fi
 
             # execute the command
-            $JAVA_HOME/bin/java $GC_OPTS $JVM_OPTS -cp $GOBBLIN_CLASSPATH 
$CLI_CLASS $CMD_PARAMS
+            $GOBBLIN_COMMAND
         fi
     # for all gobblin execution modes
     else
@@ -429,7 +430,8 @@ function start() {
 
             GOBBLIN_COMMAND="hadoop jar 
$GOBBLIN_LIB/gobblin-runtime-$GOBBLIN_VERSION.jar $MAPREDUCE_CLASS \
             -D mapreduce.job.user.classpath.first=true $JT_COMMAND $FS_COMMAND 
\
-            -libjars $MR_MODE_LIB_JARS -sysconfig 
$GOBBLIN_CONF/application.conf -jobconfig $JOB_CONF_FILE"
+            -libjars $MR_MODE_LIB_JARS -sysconfig 
$GOBBLIN_CONF/application.conf -jobconfig $JOB_CONF_FILE \
+            $LOG4J_OPTS"
 
         else
             CLASS_N_ARGS=''
diff --git a/gobblin-docs/user-guide/Gobblin-CLI.md 
b/gobblin-docs/user-guide/Gobblin-CLI.md
index d3a434a..9024ef6 100644
--- a/gobblin-docs/user-guide/Gobblin-CLI.md
+++ b/gobblin-docs/user-guide/Gobblin-CLI.md
@@ -54,7 +54,7 @@ Argument details:
 * `--jvmopts`: to specify any JVM parameters, default is `-Xmx1g -Xms512m`.
 * `--enable-gc-logs`: adds GC options to JVM parameters:  ``` 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseCompressedOops 
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution 
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$GOBBLIN_LOGS/ 
-Xloggc:$GOBBLIN_LOGS/gobblin-$GOBBLIN_MODE-gc.log ```
 * `--show-classpath`: It prints the full value of the classpath that gobblin 
uses.
-* all other arguments are sell-explanatory.
+* all other arguments are self-explanatory.
 
 Gobblin Commands
 -------------------
@@ -96,6 +96,9 @@ will provide with a list of available quick apps. To run a 
quick app:
 
 Quick apps may require additional arguments. For the usage of a particular 
app, run `bin/gobblin cli run <quick-app-name> -h`.
 
+The Distcp Quick App
+--------------------
+
 For example, consider the quick app distcp:
 ```bash
 $ gobblin cli run distcp -h
@@ -121,6 +124,42 @@ This provides usage for the app distcp, as well as listing 
all available options
 gobblin cli run distcp file:///source/path file:///target/path
 ```
 
+The OneShot Quick App
+----------------------
+
+The Gobblin cli also ships with a generic job runner, the **oneShot** quick 
app. You can use it to run a single job using a standard config file. This is 
very useful during development, testing and also makes it easy to integrate 
with schedulers that just need to fire off a command line job. The **oneShot** 
app allows you to run a job in standalone mode or in map-reduce mode.
+```bash
+$ gobblin cli run oneShot -baseConf <base-config-file> -appConf 
<path-to-job-conf-file>
+# The Base Config file is an optional parameter and contains defaults for your 
mode of
+# execution (e.g. standalone modes would typically use
+# gobblin-dist/conf/standalone/application.conf and
+# mapreduce mode would typically use 
gobblin-dist/conf/mapreduce/application.conf)
+#
+# The Job Config file is your regular .pull or .conf file and is a required 
parameter.
+# You should use a fully qualified URI to your pull file. Otherwise Gobblin 
will pick the
+# default FS configured in the environment, which may not be what you want.
+# e.g file:///gobblin-conf/my-job/wikipedia.pull or 
hdfs:///gobblin-conf/my-job/kafka-hdfs.pull
+```
+
+The **oneShot** app comes with certain hardcoded defaults (that it inherits 
from EmbeddedGobblin 
[here](https://github.com/apache/incubator-gobblin/blob/master/gobblin-runtime/src/main/resources/embedded/embedded.conf)),
 that you may not be expecting. Make sure you understand what they do and 
override them in your baseConf or appConf files if needed.
+
+Notable differences at the time of this writing include:
+
+* state.store.enabled = false (set this to true in your appConfig or 
baseConfig if you want state storage for repeated oneshot runs)
+* data.publisher.appendExtractToFinalDir = false (set this to true in your 
appConfig or baseConfig if you want to see the extract name appended to the job 
output directory)
+
+The **oneShot** app allows for specifying the log4j file of your job execution 
which can be very helpful while debugging pesky failures.
+You can launch the job in MR-Mode by using the -mrMode switch.
+
+* oneShot execution of standalone with a log4j file.
+```bash
+$ gobblin cli run oneShot -baseConf 
/app/gobblin-dist/conf/standalone/application.conf -appConf 
file:///app/kafkaConfDir/kafka-simple-hdfs.pull --log4j-conf 
/app/gobblin-dist/conf/standalone/log4j.properties
+```
+* oneShot execution of map-reduce job with a log4j file
+```bash
+$ gobblin cli run oneShot -mrMode -baseConf 
/app/gobblin-dist/conf/standalone/application.conf -appConf 
file:///app/kafkaConfDir/kafka-simple-hdfs.pull --log4j-conf 
/app/gobblin-dist/conf/standalone/log4j.properties
+```
+
 Developing quick apps for the CLI
 --------------------------------------------
     
diff --git 
a/gobblin-example/src/main/java/org/apache/gobblin/example/generic/OneShotRunner.java
 
b/gobblin-example/src/main/java/org/apache/gobblin/example/generic/OneShotRunner.java
new file mode 100644
index 0000000..501928c
--- /dev/null
+++ 
b/gobblin-example/src/main/java/org/apache/gobblin/example/generic/OneShotRunner.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.example.generic;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.apache.commons.cli.CommandLine;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+
+import org.apache.gobblin.annotation.Alias;
+import org.apache.gobblin.runtime.api.JobTemplate;
+import org.apache.gobblin.runtime.cli.CliObjectOption;
+import org.apache.gobblin.runtime.cli.PublicMethodsGobblinCliFactory;
+import org.apache.gobblin.runtime.embedded.EmbeddedGobblin;
+import org.apache.gobblin.util.JobConfigurationUtils;
+
+
+/**
+ * A class that allows Gobblin cli to run a single pull file (in a blocking 
manner) and exit on completion
+ * In contrast, a Gobblin standalone service will run forever polling
+ * for new pull files in the configured directory
+ */
+@Slf4j
+public class OneShotRunner extends EmbeddedGobblin {
+  @Alias(value = "oneShot", description = "Gobblin command that runs one pull 
file in standalone or map-reduce mode")
+  public static class CliFactory extends PublicMethodsGobblinCliFactory {
+
+
+    public CliFactory() {
+      super(OneShotRunner.class);
+    }
+
+    @Override
+    public EmbeddedGobblin constructEmbeddedGobblin(CommandLine cli) throws 
JobTemplate.TemplateException, IOException {
+      String[] leftoverArgs = cli.getArgs();
+      if (leftoverArgs.length != 0) {
+        throw new RuntimeException("Unexpected number of arguments.");
+      }
+      return new OneShotRunner();
+    }
+
+    @Override
+    public String getUsageString() {
+      return "[OPTIONS]";
+    }
+  }
+
+  @SneakyThrows
+  @CliObjectOption(description = "Runs the job in MR mode")
+  public OneShotRunner mrMode() {
+    super.mrMode();
+    return this;
+  }
+
+  @CliObjectOption(description = "Sets the base configuration file")
+  public OneShotRunner baseConf(String baseConfFile) {
+    log.info("Configured with baseConf file = {}", baseConfFile);
+    try {
+      Properties sysConfig = 
JobConfigurationUtils.fileToProperties(baseConfFile);
+      log.debug("Loaded up base config: {}", sysConfig);
+      sysConfig.entrySet()
+          .stream()
+          .forEach(pair -> super.sysConfig(pair.getKey().toString(), 
pair.getValue().toString()));
+
+    } catch (Exception e) {
+      throw new RuntimeException("Failed to load configuration from base 
config file : " + baseConfFile, e);
+    }
+    return this;
+  }
+
+  @CliObjectOption(description = "Sets the application configuration file")
+  public OneShotRunner appConf(String appConfFile) {
+    super.jobFile(appConfFile);
+    return this;
+  }
+
+  public OneShotRunner() {
+    super("Generic");
+  }
+
+}
diff --git 
a/gobblin-example/src/test/java/org/apache/gobblin/example/TestOneShotRunner.java
 
b/gobblin-example/src/test/java/org/apache/gobblin/example/TestOneShotRunner.java
new file mode 100644
index 0000000..b89e82f
--- /dev/null
+++ 
b/gobblin-example/src/test/java/org/apache/gobblin/example/TestOneShotRunner.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.gobblin.example;
+
+import java.net.URL;
+
+import org.apache.hadoop.fs.Path;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import org.apache.gobblin.example.generic.OneShotRunner;
+import org.apache.gobblin.runtime.api.Configurable;
+
+
+public class TestOneShotRunner {
+
+  @Test
+  public void testConfiguration() {
+    OneShotRunner runner = new OneShotRunner();
+    URL appConfResource = 
getClass().getClassLoader().getResource("appConf.conf");
+    URL baseConfResource = 
getClass().getClassLoader().getResource("baseConf.conf");
+    runner.appConf("file://" + appConfResource.getFile());
+    runner.baseConf("file://" + baseConfResource.getFile());
+    Assert.assertEquals(runner.getJobFile().get(), new Path("file://" + 
appConfResource.getPath()));
+    Configurable resolvedSysConfig = runner.getSysConfig();
+    Assert.assertEquals(resolvedSysConfig.getConfig().getString("test.key1"), 
"value1");
+    Assert.assertEquals(resolvedSysConfig.getConfig().getString("test.key2"), 
"value2");
+  }
+}
diff --git a/gobblin-example/src/test/resources/appConf.conf 
b/gobblin-example/src/test/resources/appConf.conf
new file mode 100644
index 0000000..791a456
--- /dev/null
+++ b/gobblin-example/src/test/resources/appConf.conf
@@ -0,0 +1 @@
+test.key2=value2-override
diff --git a/gobblin-example/src/test/resources/baseConf.conf 
b/gobblin-example/src/test/resources/baseConf.conf
new file mode 100644
index 0000000..6179ef3
--- /dev/null
+++ b/gobblin-example/src/test/resources/baseConf.conf
@@ -0,0 +1,2 @@
+test.key1=value1
+test.key2=value2
diff --git 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/embedded/EmbeddedGobblin.java
 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/embedded/EmbeddedGobblin.java
index d723ff8..ce99dbf 100644
--- 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/embedded/EmbeddedGobblin.java
+++ 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/embedded/EmbeddedGobblin.java
@@ -38,7 +38,6 @@ import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.avro.SchemaBuilder;
 import org.apache.commons.lang3.ClassUtils;
-import org.apache.gobblin.runtime.job_spec.JobSpecResolver;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
@@ -64,6 +63,13 @@ import com.linkedin.data.template.DataTemplate;
 import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
 
+import javassist.bytecode.ClassFile;
+import javax.annotation.Nullable;
+import lombok.AccessLevel;
+import lombok.Data;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
 import org.apache.gobblin.configuration.ConfigurationKeys;
 import org.apache.gobblin.configuration.State;
 import org.apache.gobblin.instrumented.extractor.InstrumentedExtractorBase;
@@ -82,15 +88,16 @@ import org.apache.gobblin.runtime.api.JobExecutionResult;
 import org.apache.gobblin.runtime.api.JobSpec;
 import org.apache.gobblin.runtime.api.JobTemplate;
 import org.apache.gobblin.runtime.api.SpecNotFoundException;
-import 
org.apache.gobblin.runtime.cli.ConstructorAndPublicMethodsGobblinCliFactory;
 import org.apache.gobblin.runtime.cli.CliObjectOption;
 import org.apache.gobblin.runtime.cli.CliObjectSupport;
+import 
org.apache.gobblin.runtime.cli.ConstructorAndPublicMethodsGobblinCliFactory;
 import org.apache.gobblin.runtime.cli.NotOnCli;
 import org.apache.gobblin.runtime.instance.SimpleGobblinInstanceEnvironment;
 import org.apache.gobblin.runtime.instance.StandardGobblinInstanceDriver;
 import org.apache.gobblin.runtime.job_catalog.ImmutableFSJobCatalog;
 import 
org.apache.gobblin.runtime.job_catalog.PackagedTemplatesJobCatalogDecorator;
 import org.apache.gobblin.runtime.job_catalog.StaticJobCatalog;
+import org.apache.gobblin.runtime.job_spec.JobSpecResolver;
 import org.apache.gobblin.runtime.job_spec.ResolvedJobSpec;
 import org.apache.gobblin.runtime.plugins.GobblinInstancePluginUtils;
 import org.apache.gobblin.runtime.plugins.PluginStaticKeys;
@@ -102,13 +109,6 @@ import org.apache.gobblin.util.HadoopUtils;
 import org.apache.gobblin.util.PathUtils;
 import org.apache.gobblin.util.PullFileLoader;
 
-import javassist.bytecode.ClassFile;
-import javax.annotation.Nullable;
-import lombok.AccessLevel;
-import lombok.Data;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
 
 /**
  * A class used to run an embedded version of Gobblin. This class is only 
intended for running a single Gobblin job.
@@ -147,6 +147,7 @@ public class EmbeddedGobblin {
   private FullTimeout shutdownTimeout = new FullTimeout(100, TimeUnit.SECONDS);
   private boolean dumpJStackOnTimeout = false;
   private List<GobblinInstancePluginFactory> plugins = Lists.newArrayList();
+  @Getter
   private Optional<Path> jobFile = Optional.absent();
 
   public EmbeddedGobblin() {
@@ -417,10 +418,14 @@ public class EmbeddedGobblin {
   public JobExecutionDriver runAsync() throws TimeoutException, 
InterruptedException {
     // Run function to distribute jars to workers in distributed mode
     this.distributeJarsFunction.run();
+    log.debug("BuiltConfigMap: {}", this.builtConfigMap);
+    log.debug("DefaultSysConfig: {}", this.defaultSysConfig);
 
     Config sysProps = ConfigFactory.parseMap(this.builtConfigMap)
         .withFallback(this.defaultSysConfig);
+    log.debug("Merged SysProps:{}", sysProps);
     Config userConfig = ConfigFactory.parseMap(this.userConfigMap);
+    log.debug("UserConfig: {}", userConfig);
 
     JobSpec jobSpec;
     if (this.jobFile.isPresent()) {
@@ -431,6 +436,8 @@ public class EmbeddedGobblin {
                 PullFileLoader.DEFAULT_JAVA_PROPS_PULL_FILE_EXTENSIONS,
                 PullFileLoader.DEFAULT_HOCON_PULL_FILE_EXTENSIONS);
         Config jobConfig = 
userConfig.withFallback(loader.loadPullFile(jobFilePath, sysProps, false));
+        log.debug("JobConfig: {}", jobConfig);
+
         ImmutableFSJobCatalog.JobSpecConverter converter =
             new 
ImmutableFSJobCatalog.JobSpecConverter(jobFilePath.getParent(), 
Optional.<String>absent());
         jobSpec = converter.apply(jobConfig);
@@ -532,7 +539,8 @@ public class EmbeddedGobblin {
     }
   }
 
-  private Configurable getSysConfig() {
+  @VisibleForTesting
+  public Configurable getSysConfig() {
     return 
DefaultConfigurableImpl.createFromConfig(ConfigFactory.parseMap(this.sysConfigOverrides).withFallback(this.defaultSysConfig));
   }
 
diff --git 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/CliMRJobLauncher.java
 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/CliMRJobLauncher.java
index a12d4a2..c580429 100644
--- 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/CliMRJobLauncher.java
+++ 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/CliMRJobLauncher.java
@@ -21,8 +21,6 @@ import java.io.IOException;
 import java.util.Properties;
 import java.util.UUID;
 
-import javax.annotation.Nullable;
-
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configured;
 import org.apache.hadoop.util.GenericOptionsParser;
@@ -31,6 +29,9 @@ import org.apache.hadoop.util.ToolRunner;
 
 import com.google.common.io.Closer;
 
+import javax.annotation.Nullable;
+import lombok.extern.slf4j.Slf4j;
+
 import org.apache.gobblin.runtime.JobException;
 import org.apache.gobblin.runtime.JobLauncher;
 import org.apache.gobblin.runtime.app.ApplicationException;
@@ -45,6 +46,7 @@ import org.apache.gobblin.runtime.listeners.JobListener;
  *
  * @author Yinan Li
  */
+@Slf4j
 public class CliMRJobLauncher extends Configured implements 
ApplicationLauncher, JobLauncher, Tool {
 
   private final Closer closer = Closer.create();
@@ -53,6 +55,8 @@ public class CliMRJobLauncher extends Configured implements 
ApplicationLauncher,
   private final MRJobLauncher mrJobLauncher;
 
   public CliMRJobLauncher(Configuration conf, Properties jobProperties) throws 
Exception {
+    log.debug("Configuration: {}", conf);
+    log.debug("Job properties: {}", jobProperties);
     setConf(conf);
     this.applicationLauncher = this.closer.register(new 
ServiceBasedAppLauncher(jobProperties,
         jobProperties.getProperty(ServiceBasedAppLauncher.APP_NAME, 
"CliMRJob-" + UUID.randomUUID())));
diff --git 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/MRJobLauncher.java
 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/MRJobLauncher.java
index 1b89ba3..720aa8c 100644
--- 
a/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/MRJobLauncher.java
+++ 
b/gobblin-runtime/src/main/java/org/apache/gobblin/runtime/mapreduce/MRJobLauncher.java
@@ -64,6 +64,8 @@ import com.typesafe.config.Config;
 import com.typesafe.config.ConfigFactory;
 import com.typesafe.config.ConfigValue;
 
+import lombok.extern.slf4j.Slf4j;
+
 import org.apache.gobblin.broker.SharedResourcesBrokerFactory;
 import org.apache.gobblin.broker.gobblin_scopes.GobblinScopeTypes;
 import org.apache.gobblin.broker.gobblin_scopes.JobScopeInstance;
@@ -122,6 +124,7 @@ import 
org.apache.gobblin.util.reflection.RestrictedFieldAccessingUtils;
  *
  * @author Yinan Li
  */
+@Slf4j
 public class MRJobLauncher extends AbstractJobLauncher {
 
   private static final String INTERRUPT_JOB_FILE_NAME = "_INTERRUPT_JOB";
@@ -253,6 +256,9 @@ public class MRJobLauncher extends AbstractJobLauncher {
             
jobProps.getProperty(ConfigurationKeys.MAXIMUM_JAR_COPY_RETRY_TIMES_KEY))
             : MAXIMUM_JAR_COPY_RETRY_TIMES_DEFAULT;
 
+    // One of the most common user mistakes is mis-configuring the FileSystem 
scheme (e.g. file versus hdfs)
+    log.info("Configured fs:{}", fs);
+    log.debug("Configuration: {}", conf);
     startCancellationExecutor();
   }
 
diff --git 
a/gobblin-utility/src/main/java/org/apache/gobblin/runtime/cli/GobblinCli.java 
b/gobblin-utility/src/main/java/org/apache/gobblin/runtime/cli/GobblinCli.java
index aa3cbd7..6a287db 100644
--- 
a/gobblin-utility/src/main/java/org/apache/gobblin/runtime/cli/GobblinCli.java
+++ 
b/gobblin-utility/src/main/java/org/apache/gobblin/runtime/cli/GobblinCli.java
@@ -22,9 +22,6 @@ import com.google.common.collect.Sets;
 import org.apache.gobblin.annotation.Alias;
 import org.apache.gobblin.util.ClassAliasResolver;
 
-import java.util.ArrayList;
-import java.util.List;
-
 
 /**
  * Instantiates a {@link CliApplication} and runs it.
@@ -47,9 +44,11 @@ public class GobblinCli {
     } catch (ReflectiveOperationException roe) {
       System.err.println("Could not find an application with alias " + alias);
       printUsage(resolver);
+      System.exit(1);
     } catch (Throwable t) {
       System.out.println("Error: " + t.getMessage());
       t.printStackTrace();
+      System.exit(2);
     }
   }
 

Reply via email to