Skip to Main Content U.S. Department of Energy

ExternalCommandModule Sample

ExternalCommandModule is used to execute an arbitrary executable and incorporate its results into a MIF pipeline. Basically, the module wraps an operating system command, which may represent an executable or script on the local system (local process) or on a remote machine (remote process).

If it is a local process, it is executed with the equivalent of the Runtime.exec() Java method. If it is a remote process, this is done by programmatically using ssh to log into the host and then executing the command. Therefore, the host on which the module is running may be running any operating system regardless of whether a native ssh executable exists.

Sample Overview

In this sample, the MIF pipeline accepts an operating system command via the command line, then executes it as a local process.

When the pipeline starts, it prompts the user for the command via a stdio inbound endpoint. The CommandBuilderModule receives the string and converts it to a MIF command object. The object is sent to the ExternalCommandModule, which forks a new process to execute that command. Finally, the output of the command is returned on the console, via a stdio oubound endpoint.

Diagram of External Command Module Sample

Note that since the command is passed in to the ExternalCommandModule instead of specified in a configuration, it is possible to choose the command to execute at runtime. It also enables the execution of an arbitrary number of command, which allows you to decide at runtime how many processes to start.

Running the Sample

To run the sample, we just start the driver class that configures the piepline, which is ExternalCommandDriver.

So, it can be started it from the command line with the command:

bin/mif.sh -c gov.pnnl.mif.samples.external.ExternalCommandDriver

Then, enter a command when prompted, for example:

enter a command[ls]: ls

This will output the contents of your working directory, for example:

CommandBuilder: created command: ExternalCommand{startCommand: ls | args: null | host: null | workingDir: null}
2010-05-27 16:56:10,905 INFO  [LocalProcess] Starting with command: [ls]
build.xml
index.html
pom.xml

Code Walkthrough

Implementing the CommandBuilder

As mentioned above, in this sample the CommandBuilder module receives a string representing a command and converts it to a ExternalCommand object, which is sent to the ExternalCommandModule. The CommandBuilder is a MifProcessor, whose listen() method is implemented as follows:

  public Serializable listen(Serializable input) {
    String startCommand = (String)input;
    if (startCommand.trim().equals("")) {
      startCommand = "ls";
    }
    ExternalCommand command = new ExternalCommand();
    command.setUser(user);
    command.setArgs(args);
    command.setHost(host);
    command.setWorkingDir(workingDir);
    command.setEnvironment(environment);
 
    command.setStartCommand(startCommand);
    System.out.println("CommandBuilder: created command: " + command);
    return command;
  }

Note that ExternalCommand object has several properties (startCommand, user, args, host, workingDir, environment) which are settable as MifModule properties. In this case, these have the default value of null so the only property set is startCommand which is the command to be run.

Remote Processes

In order to create a remote process, it is necessary to simply pass the ExternalCommandModule a ExternalCommand object with the host property set. In this case, the user property also needs to be set. In addition, the location of the MIF user's public ssh key must also be specified. For example, the following main method (not included in the sample code) creates a pipeline with an ExternalCommandMdoule which launches a remote process.

  public static void main(String[] args) {
    MifPipeline pipeline = new MifPipeline();
    MifModule builder = pipeline.addMifModule(CommandBuilder.class.getName(), "stdio://stdin?promptMessage=enter command: ", "vm://q1");
    builder.setProperty("user", "adam");
    builder.setProperty("host", "theHostName");
    ExternalCommandModule mod = pipeline.addExternalCommandModule("vm://q1", "stdio://stdout");
    mod.setProperty("sshDirectory", "/Users/adam/.ssh");
    pipeline.start();
  }
 
externalcommandmodule.txt · Last modified: 2010/05/27 17:18 by adamw