VMware Aria Automation Blog

from Stefan Schnell

Executing operating system commands offers a wide range of options for getting information or perform activities fastly, effectively and with consolidated approaches. The caller must know exactly what he wants to do, otherwise damage can also be caused. VMware Aria Automation provides the Command class for executing operating system commands. With the release 8.17.0 the class has been disabled for security reasons and will be removed in a future release. These class has some weaknesses that are eliminated by the present approach.

Execute Operating System Commands


The Advantage of this approach here are that ... This advantages gives us a better opportunity to integrate calls of operating system commands into the JavaScript runtime environment.

You can download this source also from my GitHub account.

/**
 *
 * @module de.stschnell
 *
 * @version 0.1.0
 *
 * @param {Any} in_command
 * @param {number} in_timeOut
 *
 * @outputType Any
 *
 * @description Execute a command in the host operating system
 */

function executeCommand(command, timeOut) {

// Begin ---------------------------------------------------------------

/**
 * Executes an operating system command.
 *
 * Hint: Command can be string or array of strings. If string value
 * is provided command arguments are extracted by splitting the string
 * using whitespace as separator.
 *
 * @function executeCommand
 * @param {string|string[]} command - The command to execute.
 * @param {number} timeOut - The maximum time to wait in milliseconds.
 * @returns {Object}
 *
 * @example
 * var command = [ "echo", "Hello World" ];
 * var output =
 *   System.getModule("de.stschnell").executeCommand(command).output;
 * System.log(output);
 *
 * @example
 * // Delivers on Windows:
 * // Microsoft Windows [Version 10.0.10586]
 * var command = [ "cmd", "/c", "ver" ];
 * System.log(executeCommand(command).output);
 *
 * @example
 * // Delivers on VMware Aria Automation 8.12.0:
 * // NAME="VMware Photon OS"
 * // VERSION="3.0"
 * // ...
 * var command = [ "cat", "/etc/os-release" ];
 * System.log(executeCommand(command).output);
 *
 * @example
 * // Delivers on VMware Aria Automation:
 * // Exit value: 2
 * // ls: cannot access 'bambi': No such file or directory
 * var command = [ "ls", "bambi" ];
 * System.log(executeCommand(command).output);
 *
 * Set in the VMware Control Center the system property
 * com.vmware.scripting.javascript.allow-native-object to true.
 *
 * Checked with Rhino 1.7.15, 1.7.14 and 1.7R4,
 * with Bellsoft JDK 22.0.1, 21.0.1, 17.0.9 and 11.0.21,
 * on Windows 10 and Ubuntu Linux 22.04.3 and
 * with VMware Aria Automation 8.12.0, 8.14.1 and 8.16.2
 */
function _executeCommandNS(command, timeOut) {

  if (
    typeof command === "undefined" ||
    command === null ||
    arguments.length === 0
  ) {
    throw new Error("command argument can not be undefined or null");
  }

  var _command;

  if (Array.isArray(command)) {
    _command = command;
  } else if (typeof command === "string") {
    _command = command.split(" ");
  } else {
    throw new Error("command argument must be string or array of string");
  }

  var _timeOut;

  if (
    typeof timeOut === "undefined" ||
    timeOut === null ||
    timeOut <= 1 ||
    isNaN(timeOut)
  ) {
    _timeOut = -1;
  } else {
    _timeOut = timeOut;
  }

  var output = "";
  var exitValue = -1;
  var bufferedProcessInputStream;
  var bufferedProcessErrorStream;

  try {

    var process = java.lang.Runtime.getRuntime().exec(_command);
    if (_timeOut === -1) {
      process.waitFor(); // Infinity
    } else {
      process.waitFor(
        java.lang.Long(_timeOut),
        java.util.concurrent.TimeUnit.MILLISECONDS
      );
    }
    exitValue = process.exitValue();
    if (exitValue !== 0) {
      System.error("Exit value: " + exitValue);
    }

    var processInputStream =
      java.io.InputStreamReader(process.getInputStream());
    bufferedProcessInputStream =
      java.io.BufferedReader(processInputStream);

    var processErrorStream =
      java.io.InputStreamReader(process.getErrorStream());
    bufferedProcessErrorStream =
      java.io.BufferedReader(processErrorStream);

    var line = "";

    while ((line = bufferedProcessInputStream.readLine()) !== null) {
      output += line + "\n";
    }

    while ((line = bufferedProcessErrorStream.readLine()) !== null) {
      output += line + "\n";
    }

  } catch (exception) {
    output += exception.message;
    System.error(exception);
  } finally {
    if (bufferedProcessInputStream != null) {
      bufferedProcessInputStream.close();
    }
    if (bufferedProcessErrorStream != null) {
      bufferedProcessErrorStream.close();
    }
  }

  return { "output": String(output), "exitValue": exitValue };

}

return _executeCommandNS(in_command, in_timeOut);

// End -----------------------------------------------------------------

}

The following image shows the difference between an incorrect call with executeCommand and the Command class. As can be clearly seen, an error message is returned with executeCommand, while no result is returned with the Command class. All we can see with the Command class is that the exit value is different from 0. A description of the reason, which is available, is not reported.

vmware aria automation comparison of the call of an operating system command with expected error message in stderr with executecommand and with the command class - action perspective
try {

  var command = ["ls", "bambi"];

  var output = System.getModule("de.stschnell").executeCommand(command).output;
  System.log(output);

  var orchestratorVersion =
    System.getModule("de.stschnell").getOrchestratorVersion();
  if (System.compareVersionNumber(orchestratorVersion, "8.17.0") < 0) {
    // The command object is no longer available from release 8.17.0
    var stdCommand = new Command(command);
    stdCommand.execute(true);
    var stdResult = stdCommand.result;
    if (stdResult !== 0) {
      System.error("Exit value: " + stdResult);
    }
    var stdOutput = stdCommand.output;
    System.log(stdOutput);
  }

} catch (exception) {
  System.error(exception);
}

Conclusion

With the approach presented here, operating system commands can be executed like with the VMware Aria Automation Standard, which is no longer available as of release 8.17.0. The additional options with the stderr output and a time-out parameter offer us significantly better options to handle calls of operating system commands.