Getting Started

This section will help you write and run your first NXSL script. By the end, you’ll understand the basic structure of NXSL programs and how to execute them in NetXMS.

Hello World

Every programming journey starts with a simple program. Here’s the classic "Hello World" in NXSL:

println("Hello, World!");

That’s it! This single line prints text to the output. Let’s break it down:

  • println is a built-in function that prints text followed by a newline

  • The text inside quotes "Hello, World!" is a string

  • The semicolon ; ends the statement

Running Scripts in NetXMS

NXSL scripts run in several contexts within NetXMS. Each context provides different predefined variables and expects specific return values. Here are the most common:

Execute Script (for testing or to perform one-off operation)

Right-click on any node or object and select Execute script. This runs the script in the context of the selected object, with $object (and $node if the object is a Node) automatically set.

Script Library

Access via Configuration → Script Library. Used to store reusable scripts that can be imported in other places via import script_name.

Transformation Scripts (for DCIs)

Modify collected data before storing. Set in DCI properties under Transformation.

Event Processing Policy

React to events with custom logic in EPP rules. Includes filtering scripts to decide whether to process or skip events.

Object Tools

Create custom actions available from object context menus.

nxscript (command line)

Command-line tool bundled with NetXMS server for running NXSL scripts. Useful for testing and debugging.

nxscript [options] script [arg1 [... argN]]

Common options:

-c

Compile only (syntax check)

-d

Dump compiled script code

-e <name>

Entry point (function to call)

-r

Print script return value

-t

Enable instruction trace

-m

Show memory usage information

For a complete reference of all script contexts, predefined variables, and return value semantics, see Script Execution Contexts.

Script Structure

NXSL scripts can be as simple as a single expression or more structured with functions:

// Simple script - just statements
x = 5;
y = 10;
println("Sum: " .. (x + y));

For more complex scripts, you have two approaches:

Implicit main (code outside functions):

Code outside functions is automatically wrapped into an implicit $main() function:

println("Script started");
result = calculate(5, 10);
println("Result: " .. result);
return 0;

function calculate(a, b)
{
    return a * b;
}

Explicit main function:

You can define an explicit main() function with named parameters for scripts that accept arguments:

function main(nodeName, threshold)
{
    println("Checking node:", nodeName);
    println("Threshold:", threshold);

    if (threshold == null)
        threshold = 90;  // Default value

    // ... script logic ...
    return 0;
}

With explicit main(), script parameters passed via command line or from NetXMS are mapped to function arguments in order.

If you define an explicit main() function, any code outside functions is ignored. Move all logic inside main() when using this approach.

Function definitions can be placed anywhere in the script - code outside functions executes sequentially:

println("111");
function myfunc() { println("333"); }
println("222");
myfunc();

Output:

111
222
333

Return Values

Scripts return values to their caller (NetXMS, transformation pipeline, etc.). How a script returns a value depends on whether it ends with an expression or a statement.

Expression scripts (no semicolon):

A script can be a single expression without a semicolon. The expression’s value is implicitly returned:

$1 > 100

Returns true or false. Useful for filter scripts in Event Processing Policy.

$node.status == Status::NORMAL and $node.isAgent

Returns boolean result of the compound condition.

Statement scripts (with semicolon):

When using semicolons, you must use explicit return or result will be discarded.

Result of this one will be null:

$1 > 100;

This one will return bool value as expected:

return $1 > 100;

Practical example:

Filter script for EPP (expression style - preferred for simple conditions):

$event.severity >= Severity::MAJOR

Transformation script (statement style - when logic is needed):

if ($1 == null)
    return DataCollection::ERROR;  // discard this sample
return $1 / 1024;  // Convert bytes to KB
In a transformation script, returning null does not discard the collected sample - the original (pre-transformation) value is stored instead. To discard the sample, return DataCollection::ERROR, DataCollection::NO_SUCH_INSTANCE, or DataCollection::NOT_SUPPORTED.

Comments

Document your code with comments:

// Single-line comment

/*
   Multi-line comment
   spanning several lines
*/

x = 5; // Inline comment

Basic Input and Output

Output:

  • println(value, …​) - Print one or more values (separated by spaces) followed by a newline

  • print(value, …​) - Print one or more values (separated by spaces) without newline

  • trace(level, message) - Diagnostic output written to the server debug console and log file (nxsl.trace tag). Level 0 always writes an INFO log entry; messages with level above 0 are written only when the current debug level is equal to or above the specified level

println("Sum:", x, "+", y, "=", x + y);  // Prints: Sum: 5 + 10 = 15
trace(3, "Processing node " .. $node.name);  // Shows when debug level >= 3

Script Parameters:

Scripts receive parameters through special variables $1, $2, etc. All arguments are also available as an array in the global variable $ARGS:

// If script called with parameters "hello" and "world"
println($1);  // Prints: hello
println($2);  // Prints: world

// Using $ARGS array (1-indexed)
println($ARGS[1]);  // Prints: hello
println($ARGS[2]);  // Prints: world

// Iterate over all arguments
for (i = 1; i <= $ARGS.size; i++)
    println("Arg", i, "=", $ARGS[i]);

Your First Practical Script

Let’s write a script that does something useful - converting a UNIX timestamp to human-readable format:

// Transform UNIX timestamp to readable date
// Use as transformation script for timestamp DCIs

if ($1 == null)
    return DataCollection::ERROR;  // discard this sample

return DateTime($1).format("%Y-%m-%d %H:%M:%S");

This script:

  1. Checks if input ($1) is null and discards the sample if so (returning null from a transformation script would store the original value instead)

  2. Creates a DateTime object and formats it

  3. Returns the formatted string

Error Handling Basics

Always consider what happens when things go wrong:

value = GetDCIValue($node, 123);
if (value == null)
{
    trace(1, "Failed to get DCI value");
    return null;
}
println("Value: " .. value);

Key practices:

  • Check for null after operations that might fail

  • Use trace() for debugging information

  • Return appropriate values for error conditions

Safe navigation operator:

For simpler null handling when accessing object members, use the safe navigation operator ?.:

node = FindObject("my-server");
println(node?.name);  // Prints nothing if node is null (no error)

// Chain method calls safely
result = $node.createSNMPTransport()?.getValue("1.3.6.1.2.1.1.1.0");

This avoids nested null checks while preventing runtime errors on null objects.

Next Steps

Now that you can write and run basic scripts, explore: