Calling Programs

Calling programs or command line scripts is a very powerful feature that can be used to check configuration of the system or perform advanced automation steps.

Additionally, you can access information about the underlying system, e.g. the operating system type/name and environmental variables in order to tailor your script to work across multiple os types.

Because of the power of this automation, it can be disabled centrally by using the Security.EnableOSCodeExec parameter from the Administration → Settings page.

Options are to disable globally, enable only for non-root users and enable globally.

Code Walkthrough

The os global variable is the key object to allow access to the underlying operating system and information about the operating system in use.

Calling a simple program

In the following very simple check we will use the built in command whoami to report back the user that the agent is running under.

Using the method exec(..) we can simply call the command. This method returns an ExecResult object and the command line output is simply available on the out property. In this simple check, we set that to the check message property to create a simple JavaScript based custom check that can be run on all monitored system types:

const agentUser = os.exec("whoami");

check.message = agentUser.out;

Handling Errors

The above example works for simple commands that you know will execute, but perhaps this command could also throw an error which would need to be checked. The ExecResult object has a property exitCode that can be used to control the flow of your check.

let willFail;

try {
    willFail = os.exec("this_doesnt_exist");
} catch (e) {
    // Catch any exception (raised on Windows)
    // and create an object with our results:
    willFail = {
        out: e.getMessage(),
        exitCode: -1
    };
}

// Format the message output as the command output
check.message = willFail.out;

if (willFail.exitCode != 0) {
    // Handle the error case
    // check.status is by default OK
    check.status = CRITICAL;
}

This check will always fail (unless for some reason you have a command called this_doesnt_exist available) to demonstrate this feature. We always set the check message to contain the output the command produced, in this case something like command not found is printed but this depends on the operating system. And we set the status of the check to CRITICAL in this error case.

Handling OS differences

Sometimes the command to execute will differ between operating systems. You can use the osName property to differentiate between operating systems in your landscape and call different commands, or add different options depending on the type. This means you have a single custom check that can be rolled out to all servers rather than needing to define specific system selectors for different checks and future changes in check logic need only be made in one place.

Using the osName property is simple as seen in this example that will output the running processes in both Windows and Linux environments.

const isWindows = os.osName.toLowerCase().indexOf("windows") > -1;

let cmd = '';

if (isWindows) {
    cmd = "tasklist";
} else {
    cmd = "ps aux"
}

check.message = os.exec(cmd).out;

The check message is simply the text output, you could extend this check further to create a table of results. Note that the different operating systems commandes return the information in different formats, and on Windows, the line endings are different and may need to be handled differently. See the examples section for the full code for this.

Developing such multi-os checks are accelerated with the test run feature for custom JavaScript checks. Here you can add multiple systems (choose one Linux and one Windows) and see the result of your changes in both systems immediately.

Using Cloud APIs

With the cloudMetaData property on the os global object, we also have access to information the virtualisation provider has about this virtual machine. For example in Google Cloud Platform (GCP):

const cloudMD = os.cloudMetaData;

if (cloudMD) {
    const project = cloudMD["project-id"];
    const name = cloudMD.name;

    console.log(`Running in GCP ${project} / ${name}`);
}

The structure of cloudMetaData is dependant on the cloud/virtualisation provider in use and can be changed at any time by the provider.

You can console.log(JSON.stringify(os.cloudMetaData)) to work out what properties are available in your scripts while developing.

Examples

Example 1. Example: Get the content of the /opt directory

The example is a bit silly, but it demonstrates how it works. Simply create a JavaScript based custom check (RUN_JS) for a Linux server, copy & paste the code example below, and you can see it work.

const result = os.exec("sh -c 'ls -al /opt'");

if (result.exitCode === 0) {
    check.status = OK;
    check.message = "The content of directory /opt is:\n";
}
else {
    check.status = WARNING;
    check.message = "Command failed!\n";
}

check.message = check.message + result.out;
Example 2. Example: Cross-Platform Process List

This example is an extension of the cross-platform code walkthrough that will format the output of the process list command in a custom check.

const isWindows = os.osName.toLowerCase().indexOf("windows") > -1;

// on Windows, we call 'tasklist'
// whereas on Linux based systems it's  'ps aux'
const cmd = isWindows ? "tasklist" : "ps aux";
// Each command has a different number of header rows
const skipRows = isWindows ? 3 : 1;

// Call the command and split the output by each line
const rows = os.exec(cmd).out.split('\n');

// Create a table output with two columns:
// |   PID   |   Name   |
check.addTableColumn("PID");
check.addTableColumn("Name");

// Process each row
rows.forEach((row, index) => {
    // Skip the header rows
    if (index < skipRows) return;

    // Split the row by whitespace
    const parts = row.split(/\s+/);
    if (parts.length > 1) {
        // Create a new row in the table
        check.newRow();

        // The process id is always 2nd in the table
        const pid = parts[1];
        // The name of the process is in different columns
        const name = isWindows ? parts[0] : parts[10];

        // Add the data to the check output
        check.addCell(pid);
        check.addCell(name);
    }
});

API Reference

Global Variable os

The global variable os is used to access the operating system of the managed object. Using the powerful exec methods allow access to collect information or perform actions by executing built in or custom programs at the operating system level.


exec(..)

exec(commandLine: string): ExecResult

Execute a command on the operating system of the Agent.

Specify a shell/terminal command to execute as you would enter a command in a command line environment directly on the operating system. Please note that operating system commands may be disabled by system-wide settings.

If the command creates files or performs tasks, make sure to clean up after the command has been executed.

This command will wait for 30s before exiting.

Parameters
  • commandLine: string

    command line argument to execute

Returns

ExecResult

the result of the execution


exec(..)

exec(commandLine: string, timeoutMs: number): ExecResult

Execute a command on the operating system of the Agent.

Specify a shell/terminal command to execute as you would enter a command in a command line environment directly on the operating system. Please note that operating system commands may be disabled by system-wide settings.

If the command creates files or performs tasks, make sure to clean up after the command has been executed.

This command will wait for the specified time given in ms to the parameter timeoutMS before exiting.

Parameters
  • commandLine: string

    command line argument to execute

  • timeoutMs: number

    the timeout in ms to wait until failure

Returns

ExecResult

the result of the execution


execSSH(..)

execSSH(credentials: any, commandLine: string): ExecResult

Executes the given command with the user set in credentials (with no timeout).

Example:

// Use with automation credentials:
const osCmd = database.execSSH(action.input.db_user, 'id');

console.log(osCmd.exitCode); // Print exit code
console.log(osCmd.out);      // Print command result
Since

21.11.4

Parameters
  • credentials: any

    the credentials used to execute the command

  • commandLine: string

    command line argument to execute

Returns

ExecResult

the result of the execution


execSSH(..)

execSSH(credentials: any, commandLine: string, timeoutMs: number): ExecResult

Executes the given command with the user set in credentials.

Example:

// Use with automation credentials:
const osCmd = database.execSSH(action.input.db_user, 'id', 10000);

console.log(osCmd.exitCode); // Print exit code
console.log(osCmd.out);      // Print command result
Since

21.11.4

Parameters
  • credentials: any

    the credentials used to execute the command

  • commandLine: string

    command line argument to execute

  • timeoutMs: number

    the timeout in ms to wait until failure (set to 0 to set no timeout)

Returns

ExecResult

the result of the execution


getCloudMetaData( )

getCloudMetaData(): any

If the monitored object is running on a supported hyper-visor environment, e.g. Google Compute Platform, return a JSON object of information we’ve retrieved about this virtual machine and this environment.

Avantra uses this information to enrich our landscape information in the server UI, however a check developer could use this information to perform additional web API calls to perform actions on this environment or to report other useful information back to Avantra.

Since

21.11

Returns

any

a JSON object or null if not running on a supported hyper-visor

See Also

getOsName( )

getOsName(): string

Return the type of operating system that this Agent is running on.

This can be used to tailor specific commands to the operating system in use so that the checks or automation can be made generic across OS type.

Returns

string

the name of the underlying operating system

See Also

getenv(..)

getenv(name: string): string

Returns the value of a specific environment variable set for this execution of the check on the Agent.

Parameters
  • name: string

    the name of the environment variable

Returns

string

the value of the environment variable


cloudMetaData

readonly cloudMetaData: any

If the monitored object is running on a supported hyper-visor environment, e.g. Google Compute Platform, return a JSON object of information we’ve retrieved about this virtual machine and this environment.

Avantra uses this information to enrich our landscape information in the server UI, however a check developer could use this information to perform additional web API calls to perform actions on this environment or to report other useful information back to Avantra.

See Also
Type

any

Modifiers

Readonly

Since

21.11


osName

readonly osName: string

Return the type of operating system that this Agent is running on.

This can be used to tailor specific commands to the operating system in use so that the checks or automation can be made generic across OS type.

See Also
Type

string

Modifiers

Readonly


Class ExecResult

This class captures the response of executing a command on the operating system.

getExitCode( )

getExitCode(): number

Returns the exit code from executing the command

Returns

number

the exit code of the command executed

See Also

getOut( )

getOut(): string

Returns the output of the command (i.e. the output of the command line console when the command is executed).

Returns

string

the console output/result of the command

See Also

exitCode

readonly exitCode: number

The exit code of the command executed

See Also
Type

number

Modifiers

Readonly


out

readonly out: string

The command line output of the command executed.

See Also
Type

string

Modifiers

Readonly