## Command Execution Functions
Execute shell commands and capture output (requires --trust flag).
Execute external commands from templates. These functions provide the ability to run shell commands and capture their output.
**SECURITY WARNING:** Command execution is a powerful feature that can pose security risks. These functions are **only available in trust mode** (`--trust` flag).
#### `exec(command, timeout)`
Execute a command and return stdout as a string. Throws an error if the command fails (non-zero exit code).
**Arguments:**
- `command` (required) - Command to execute (executed via system shell)
- `timeout` (optional) - Timeout in seconds (default: 30, max: 300)
**Returns:** Standard output as string
**Security:** Only available with `--trust` flag
**Examples:**
```jinja
{# Simple usage - get output directly #}
Hostname: {{ exec(command="hostname") }}
{# Use with filters #}
{# Use in variable #}
{% set git_hash = exec(command="git rev-parse --short HEAD 2>/dev/null || echo 'unknown'") %}
Commit: {{ git_hash | trim }}
{# This will throw an error if command fails #}
{{ exec(command="ls /nonexistent") }} {# Error! #}
```
#### `exec_raw(command, timeout)`
Execute a command and return a detailed result object. Never throws based on exit code - you control all error handling.
**Arguments:**
- `command` (required) - Command to execute (executed via system shell)
- `timeout` (optional) - Timeout in seconds (default: 30, max: 300)
**Returns:** Object with fields:
- `exit_code` - Exit code (integer, 0 = success)
- `stdout` - Standard output (string)
- `stderr` - Standard error (string)
- `success` - Boolean (true if exit_code == 0)
**Security:** Only available with `--trust` flag
**Examples:**
```jinja
{# Full control over result #}
{% set result = exec_raw(command="ls -la /tmp") %}
{% if result.success %}
Files:
{{ result.stdout }}
{% else %}
Error (exit {{ result.exit_code }}): {{ result.stderr }}
{% endif %}
{# Handle expected non-zero exit (e.g., grep) #}
{% set result = exec_raw(command="grep foo /etc/hosts") %}
{% if result.exit_code == 0 %}
Found: {{ result.stdout }}
{% elif result.exit_code == 1 %}
Not found
{% else %}
Error: {{ result.stderr }}
{% endif %}
{# Check if a tool is available #}
{% set docker = exec_raw(command="which docker") %}
{% if docker.success %}
Docker not installed
{% endif %}
```
**Practical Example - Build Information:**
```yaml
build:
date: {{ exec(command="date -u +%Y-%m-%dT%H:%M:%SZ") | trim }}
user: {{ exec(command="whoami") | trim }}
```
**Practical Example - Conditional Configuration:**
```yaml
{% set node_check = exec_raw(command="which node") %}
{% set docker_check = exec_raw(command="which docker") %}
services:
node_version: {{ exec(command="node --version") | trim }}
{% endif %}
docker_path: {{ docker_check.stdout | trim }}
{% endif %}
```
**Practical Example - Dynamic Worker Configuration:**
```yaml
{% set cpu_count = exec(command="nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo '2'") | trim | int %}
workers:
count: {{ cpu_count * 2 }}
per_worker_connections: 1000
total_capacity: {{ cpu_count * 2000 }}
```
**Security Considerations:**
⚠️ **Command Injection Risk:** Never use untrusted input in commands
```jinja
{# ❌ DANGEROUS - DO NOT DO THIS #}
{% set user_input = get_env(name="USER_INPUT") %}
{{ exec(command="echo " ~ user_input) }} {# COMMAND INJECTION! #}
{# ✓ SAFE - Use only hardcoded, trusted commands #}
{{ exec(command="hostname") }}
{{ exec(command="date") }}
```
**Notes:**
- Commands are executed via the system shell (`sh -c` on Unix, `cmd /C` on Windows)
- All shell features work: pipes (`|`), redirections (`>`, `2>&1`), command substitution (`$()`)
- Use `exec()` for simple cases where you just want output
- Use `exec_raw()` when you need to check exit codes or handle errors
- Always use `2>/dev/null || echo 'fallback'` patterns for robust error handling
- Keep commands fast - they block template rendering