DEV Community

Pirate Prentice
Pirate Prentice

Posted on

n8n Execute Command Node: Run Shell Scripts and CLI Tools in Your Workflows (Free JSON)

The n8n Execute Command node lets you run any shell command directly inside your workflow. Use it to call CLI tools, run scripts, invoke system utilities, or chain shell pipelines — all without leaving n8n.

This guide covers everything: configuration, environment variables, common patterns, error handling, and a free workflow JSON you can import right now.

What the Execute Command Node Does

The Execute Command node runs a shell command on the machine where n8n is hosted and returns:

  • stdout — the command output
  • stderr — error output (if any)
  • exitCode — 0 = success, non-zero = failure

It runs synchronously inside your workflow, so downstream nodes receive the output immediately.

Important: This node only works on self-hosted n8n. It is not available on n8n Cloud.

Basic Configuration

In the node settings:

Field What to set
Command The shell command to execute (e.g., ls -la /tmp)
Execute Once Run once per execution (vs. once per input item)

The command runs in the shell defined by the SHELL environment variable (defaults to /bin/sh on Linux/macOS).

Using Input Data in Commands

You can reference data from previous nodes using n8n expressions:

Command: python3 /opt/scripts/process.py --id={{ $json.record_id }} --env={{ $json.environment }}
Enter fullscreen mode Exit fullscreen mode

Security note: Never interpolate untrusted user input directly into a shell command — this creates command injection risk. Sanitize or validate input before use, or pass data via environment variables instead.

Passing Environment Variables

For secrets and dynamic values, use the Environment Variables section in the node (instead of interpolating into the command string):

Environment Variables:
  API_KEY = {{ $env.MY_API_KEY }}
  RECORD_ID = {{ $json.record_id }}

Command: python3 /opt/scripts/process.py
Enter fullscreen mode Exit fullscreen mode

The script reads os.environ["RECORD_ID"] — safe, no injection risk.

Reading the Output

The node outputs a JSON item with:

{
  "stdout": "output text here",
  "stderr": "",
  "exitCode": 0
}
Enter fullscreen mode Exit fullscreen mode

Access stdout in downstream nodes with {{ $json.stdout }}.

For structured output, have your script print JSON and parse it in a Code node downstream.

Common Patterns

Run a Python Script on a Schedule

Schedule Trigger (daily 03:00)
→ Execute Command (python3 /opt/scripts/daily_report.py)
→ Send Email (body: {{ $json.stdout }})
Enter fullscreen mode Exit fullscreen mode

Compress and Upload a File

Trigger
→ Execute Command (tar -czf /tmp/backup.tar.gz /var/data/exports/)
→ S3 Upload (binary: /tmp/backup.tar.gz)
→ Execute Command (rm /tmp/backup.tar.gz)
Enter fullscreen mode Exit fullscreen mode

Call a CLI Tool and Parse Output

Webhook
→ Execute Command (aws s3 ls s3://{{ $json.bucket }}/ --recursive | wc -l)
→ Code (return [{ json: { fileCount: parseInt($input.first().json.stdout.trim()) } }])
→ Respond to Webhook
Enter fullscreen mode Exit fullscreen mode

Database Backup with pg_dump

Schedule Trigger (weekly Sunday 02:00)
→ Execute Command (pg_dump -U $DB_USER $DB_NAME > /tmp/backup.sql)
→ S3 Upload (key: backups/{{ $now.format('yyyy-MM-dd') }}.sql)
→ Execute Command (rm /tmp/backup.sql)
Enter fullscreen mode Exit fullscreen mode

Error Handling

By default, if a command returns a non-zero exit code, n8n treats it as an error and stops the workflow.

To handle errors gracefully, use the Continue On Fail option in the node settings:

  • Enable Continue On Fail → downstream nodes receive exitCode and stderr even on failure
  • Check {{ $json.exitCode }} in an IF node to branch on success/failure
  • Log {{ $json.stderr }} to a monitoring workflow

Gotchas Table

Symptom Root cause Fix
Command not found Binary not in PATH for the shell n8n uses Use full path (e.g., /usr/bin/python3) or set PATH in env vars
Works in terminal, fails in n8n Different shell user or environment Test with Execute Command: whoami; check n8n process user
Timeout / no output Command waits for stdin Add --no-interaction flags or pipe /dev/null
stderr treated as error Non-zero exit from a warning Enable Continue On Fail; check exitCode in IF node
File not found Relative path resolves from n8n working dir Always use absolute paths
Secrets visible in logs Secret interpolated into command string Pass secrets via Environment Variables field, not command

Free Workflow JSON — Scheduled Script Runner

This workflow runs a script on a schedule, captures output, and emails a report or alert:

{
  "name": "Scheduled Script Runner",
  "nodes": [
    {
      "parameters": { "rule": { "interval": [{ "field": "hours", "hoursInterval": 24 }] } },
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [250, 300]
    },
    {
      "parameters": {
        "command": "python3 /opt/scripts/daily_report.py",
        "executeOnce": true
      },
      "name": "Run Script",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [480, 300]
    },
    {
      "parameters": {
        "conditions": {
          "number": [{ "value1": "={{ $json.exitCode }}", "operation": "equal", "value2": 0 }]
        }
      },
      "name": "Success?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [710, 300]
    },
    {
      "parameters": {
        "fromEmail": "ops@yourdomain.com",
        "toEmail": "team@yourdomain.com",
        "subject": "Daily Report",
        "text": "={{ $json.stdout }}"
      },
      "name": "Email Report",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 1,
      "position": [940, 200]
    },
    {
      "parameters": {
        "fromEmail": "ops@yourdomain.com",
        "toEmail": "team@yourdomain.com",
        "subject": "FAILED: Daily Report",
        "text": "={{ 'Exit code: ' + $json.exitCode + '\n\nStderr:\n' + $json.stderr }}"
      },
      "name": "Alert on Failure",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 1,
      "position": [940, 400]
    }
  ],
  "connections": {
    "Schedule Trigger": { "main": [[{ "node": "Run Script", "type": "main", "index": 0 }]] },
    "Run Script": { "main": [[{ "node": "Success?", "type": "main", "index": 0 }]] },
    "Success?": {
      "main": [
        [{ "node": "Email Report", "type": "main", "index": 0 }],
        [{ "node": "Alert on Failure", "type": "main", "index": 0 }]
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Drop a comment with what you're running — I'll share a version tailored to your use case (backup, ETL, CLI tool, etc.).

Workflow Starter Pack ($29)

If you want production-ready workflows with error handling, retry logic, environment variable patterns, and monitoring already built in, the n8n Workflow Starter Pack includes an Execute Command workflow alongside 10+ other automation patterns.

Every workflow is documented, tested, and imports in under 2 minutes.


What CLI tools or scripts do you run from n8n? Let me know in the comments — always curious what people automate.

Top comments (1)

Collapse
 
pirateprentice profile image
Pirate Prentice

What CLI tools or scripts are you running from n8n? I've seen people automate pg_dump backups, Python ETL scripts, and ffmpeg pipelines — drop your use case below and I'll share a tailored workflow snippet. Also just published the FTP/SFTP node guide if you need to transfer files to legacy servers after your script runs.