Skip to content

Guide System Commands

Kris Simon edited this page Mar 1, 2026 · 5 revisions

System Commands

ARO provides the Exec action for executing shell commands on the host system. This chapter covers command execution, result handling, and security considerations.

Basic Execution

Preferred Syntax

The preferred syntax places the command name in the object specifier:

(* Simple command *)
Exec the <result> for the <command: "uptime">.

(* Command with arguments *)
Exec the <result> for the <command: "ls"> with "-la".

(* Command with multiple arguments *)
Exec the <result> for the <command: "ls"> with ["-l", "-a", "-h"].

This syntax clearly separates the command from its arguments, making code more readable.

Legacy Syntax

The legacy syntax with full command in the with clause is still supported:

Exec the <result> for the <command> with "ls -la".
Exec the <listing> for the <files> with "find . -name '*.txt'".
Exec the <status> for the <check> with "git status".

Using Variables

Build commands dynamically with variables:

Create the <directory> with "/var/log".
Exec the <result> for the <command: "ls"> with "-la ${directory}".

Create the <pattern> with "*.aro".
Exec the <files> for the <command: "find"> with [". ", "-name", "${pattern}"].

Result Object

Every Exec action returns a structured result object:

Field Type Description
error Boolean true if command failed (non-zero exit code)
message String Human-readable status message
output String Command stdout (or stderr if error)
exitCode Int Process exit code (0 = success, -1 = timeout)
command String The executed command string

Accessing Result Fields

Exec the <result> for the <command> with "whoami".

(* Access individual fields *)
Log <result.output> to the <console>.
Log <result.exitCode> to the <console>.

(* Check for errors *)
Log <result.message> to the <console> when <result.error> = true.

Error Handling

Checking for Errors

(Check Disk Space: System Monitor) {
    Exec the <result> for the <disk-check> with "df -h".

    Log <result.message> to the <console> when <result.error> = true.
    Return an <Error: status> with <result> when <result.error> = true.

    Return an <OK: status> with <result>.
}

Handling Non-Zero Exit Codes

(Git Status: Version Control) {
    Exec the <result> for the <git> with "git status --porcelain".

    Log "Not a git repository" to the <console> when <result.exitCode> != 0.
    Return a <BadRequest: status> with { error: "Not a git repository" } when <result.exitCode> != 0.

    Return an <OK: status> with { message: "Working tree clean" } when <result.output> is empty.

    Return an <OK: status> with { changes: <result.output> }.
}

Timeout Handling

Commands that exceed the timeout return with exitCode: -1:

Exec the <result> for the <long-task> with {
    command: "sleep 60",
    timeout: 5000
}.

Log "Command timed out" to the <console> when <result.exitCode> = -1.

Configuration Options

For advanced control, use object syntax:

Exec the <result> on the <system> with {
    command: "npm install",
    workingDirectory: "/app",
    timeout: 60000,
    shell: "/bin/bash",
    environment: { NODE_ENV: "production" }
}.

Available Options

Option Type Default Description
command String (required) The shell command to execute
workingDirectory String current Working directory for the command
timeout Int 30000 Timeout in milliseconds
shell String /bin/sh Shell to use for execution
environment Object (inherited) Additional environment variables
captureStderr Boolean true Include stderr in output

Context-Aware Output

ARO's context-aware response formatting means Exec results display differently based on execution context.

Console Output (Human Context)

command: ls -la
exitCode: 0
error: false
message: Command executed successfully
output:
  total 48
  drwxr-xr-x  12 user  staff   384 Dec 23 10:00 .
  -rw-r--r--   1 user  staff  1234 Dec 23 10:00 main.aro

HTTP Response (Machine Context)

{
    "status": "OK",
    "reason": "success",
    "data": {
        "result": {
            "error": false,
            "message": "Command executed successfully",
            "output": "total 48\ndrwxr-xr-x  12 user  staff...",
            "exitCode": 0,
            "command": "ls -la"
        }
    }
}

Common Patterns

Directory Listing

(Application-Start: Directory Lister) {
    Log "Directory Lister" to the <console>.
    Exec the <listing> for the <command> with "ls -la".
    Return an <OK: status> for the <listing>.
}

System Information

(System Info: Status API) {
    Exec the <hostname> for the <command: "hostname">.
    Exec the <uptime> for the <command: "uptime">.
    Exec the <memory> for the <command: "free"> with "-h".

    Create the <info> with {
        hostname: <hostname.output>,
        uptime: <uptime.output>,
        memory: <memory.output>
    }.

    Return an <OK: status> with <info>.
}

Build Pipeline

(Run Build: CI Pipeline) {
    Log "Installing dependencies..." to the <console>.
    Exec the <install> for the <npm> with {
        command: "npm install",
        workingDirectory: "./app",
        timeout: 120000
    }.

    Return an <Error: status> with <install> when <install.error> = true.

    Log "Running tests..." to the <console>.
    Exec the <test> for the <npm> with {
        command: "npm test",
        workingDirectory: "./app"
    }.

    Return an <Error: status> with <test> when <test.error> = true.

    Log "Building..." to the <console>.
    Exec the <build> for the <npm> with {
        command: "npm run build",
        workingDirectory: "./app"
    }.

    Return an <OK: status> with <build>.
}

Health Checks

(Health Check: Monitoring) {
    Exec the <curl> for the <health> with {
        command: "curl -s http://localhost:8080/health",
        timeout: 5000
    }.

    Return a <ServiceUnavailable: status> with {
        service: "api",
        error: <curl.message>
    } when <curl.error> = true.

    Return an <OK: status> with { healthy: true }.
}

Process Management

(List Processes: Admin API) {
    Exec the <processes> for the <list> with "ps aux | head -20".
    Return an <OK: status> with <processes>.
}

(Check Process: Admin API) {
    Extract the <name> from the <queryParameters: name>.
    Exec the <result> for the <check> with "pgrep -l ${name}".

    Return an <OK: status> with { running: false, process: <name> } when <result.error> = true.

    Return an <OK: status> with { running: true, process: <name>, pids: <result.output> }.
}

Security Considerations

Command Injection Prevention

Be cautious when constructing commands from user input:

(* DANGEROUS - user input directly in command *)
Exec the <result> for the <command> with "ls ${userInput}".

(* SAFER - validate input first *)
Validate the <path> for the <userInput> against "^[a-zA-Z0-9_/.-]+$".
Return a <BadRequest: status> with "Invalid path characters" when <path> is not <valid>.
Exec the <result> for the <command> with "ls ${path}".

Best Practices

  1. Never trust user input - Always validate and sanitize before using in commands
  2. Use allowlists - Define allowed commands or patterns rather than blocking bad ones
  3. Limit permissions - Run the ARO application with minimal required privileges
  4. Set timeouts - Always specify reasonable timeouts to prevent hanging
  5. Log commands - Keep audit logs of executed commands for security review

Sandboxing (Future)

Future versions may support sandboxing options:

Exec the <result> for the <command> with {
    command: "npm install",
    sandbox: {
        network: false,
        filesystem: ["/app"],
        maxMemory: "512MB",
        maxTime: 60000
    }
}.

Next Steps

Clone this wiki locally