<Command>
The <Command> block executes shell commands or scripts with variable substitution. It’s used for performing operations like deployments, resource creation, and system configuration.
Basic Usage
Section titled “Basic Usage”<Command id="trigger-deploy" command="curl -X POST https://api.example.com/deploy" title="Trigger Deployment" successMessage="Deployment triggered!" failMessage="Failed to trigger deployment"/>vs. Check
Section titled “vs. Check”Command blocks and Check blocks share many features in common, however they each have a distinct purpose. Check blocks are focused on reading the state of the world and validating it, while Command blocks are focused on mutating the state of the world to update it to what is needed.
Required Props
Section titled “Required Props”id(string) - Unique identifier for this command block
Optional Props
Section titled “Optional Props”title(string) - Display title shown in the UI. Supports inline markdown (bold, italic, links, code).description(string) - Longer description of what the command does. Supports inline markdown.command(string) - Inline command to execute (alternative topath)path(string) - Path to a shell script file relative to the runbook (alternative tocommand)inputsId(string | string[]) - ID of an Inputs block to get template variables from. Can be a single ID or an array of IDs. When multiple IDs are provided, variables are merged in order (later IDs override earlier ones).awsAuthId(string) - ID of an AwsAuth block for AWS credentials. The credentials are passed as environment variables (AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN,AWS_REGION).successMessage(string) - Message shown when command succeeds (default: “Success”). Supports inline markdown.failMessage(string) - Message shown when command fails (default: “Failed”). Supports inline markdown.runningMessage(string) - Message shown while running (default: “Running…”). Supports inline markdown.
Inline content
Section titled “Inline content”Instead of referencing an external <Inputs> block via inputsId, you can nest an <Inputs> component directly inside the Command:
<Command id="echo-message" command='echo "Hello, {{ .Name }}!"' title="Print Greeting"> <Inputs id="inline-greeting"> ```yaml variables: - name: Name type: string description: Your name validations: "required" \``` </Inputs></Command>The embedded <Inputs> renders directly within the Command block, allowing users to fill in variables before running the command.
Other blocks can reference this Inputs block using the standard inputsId pattern.
Writing Scripts
Section titled “Writing Scripts”Command blocks run shell scripts to perform operations like deployments, installations, and configuration changes.
Scripts can be defined inline using the command prop or stored in external files using the path prop.
When writing scripts for Command blocks:
- Exit codes matter. Return
0for success, any other code for failure - Use logging helpers. Standardized functions like
log_infoandlog_errorare available - Templatize with variables. Use
{{ .VariableName }}syntax to inject user input
Scripts run in a non-interactive shell environment. See Execution Context for details.
Defining Scripts
Section titled “Defining Scripts”You can write scripts either inline or by referencing script files.
Inline Scripts
Section titled “Inline Scripts”For simple commands, you can define the script directly in the command prop:
<Command id="deploy-trigger" command="curl -X POST https://api.example.com/deploy" title="Trigger Deployment" successMessage="Deployment triggered!" failMessage="Failed to trigger deployment"/>Inline scripts work best for one-liners or short commands. For anything more complex, use an external script file.
External Scripts
Section titled “External Scripts”Instead of inline commands, you can reference external shell scripts:
<Command id="deploy-app" path="scripts/deploy.sh" title="Deploy Application" description="This will deploy your application to production" successMessage="Deployment successful!" failMessage="Deployment failed. Check the logs for details."/>External scripts are plain old bash scripts. The referenced script scripts/deploy.sh might look like:
#!/bin/bash
log_info "Starting deployment..."kubectl apply -f deployment.yaml
if kubectl rollout status deployment/myapp; then log_info "Deployment complete!" exit 0else log_error "Deployment failed" exit 1fiExit Codes
Section titled “Exit Codes”The Command block interprets your script’s exit codes as follows:
- Exit code 0: Success ✓ (green)
- Any other exit code: Failure ✗ (red)
These exit codes will determine how the Runbooks UI renders the result of running a script.
Logging
Section titled “Logging”Runbooks provides standardized logging functions for your scripts by automatically importing a logging.sh file that defines a standardized set of Bash logging functions. Using these functions enables consistent output formatting and allows the Runbooks UI to parse log levels for filtering and export.
Log Levels
Section titled “Log Levels”| Function | Output | Description |
|---|---|---|
log_info "msg" | [timestamp] [INFO] msg | General informational messages |
log_warn "msg" | [timestamp] [WARN] msg | Warning conditions |
log_error "msg" | [timestamp] [ERROR] msg | Error messages |
log_debug "msg" | [timestamp] [DEBUG] msg | Debug output (only when DEBUG=true) |
Usage Example
Section titled “Usage Example”#!/bin/bashlog_info "Starting deployment..."log_debug "Target environment: $ENVIRONMENT"
if [ -z "$API_KEY" ]; then log_warn "API_KEY not set, some features may be unavailable"fi
if ! deploy_application; then log_error "Deployment failed" exit 1fi
log_info "Deployment complete"Local Development
Section titled “Local Development”When running scripts locally (outside the Runbooks UI), the logging functions won’t magically be pre-loaded, so if you’d like your scripts to run successfully both locally and in the Runbooks environment, copy/paste this snippet to the top of your script:
# --- Runbooks Logging (https://runbooks.gruntwork.io/authoring/blocks/command#logging) ---if ! type log_info &>/dev/null; then source <(curl -fsSL https://raw.githubusercontent.com/gruntwork-io/runbooks/main/scripts/logging.sh 2>/dev/null) 2>/dev/null type log_info &>/dev/null || { log_info() { echo "[INFO] $*"; }; log_warn() { echo "[WARN] $*"; }; log_error() { echo "[ERROR] $*"; }; log_debug() { [ "${DEBUG:-}" = "true" ] && echo "[DEBUG] $*"; }; }fi# --- End Runbooks Logging ---This snippet checks if the logging functions are already defined, attempts to fetch them from GitHub, and falls back to simple implementations if offline.
With Variables
Section titled “With Variables”There are several ways to collect variables to customize a command or script.
Using inputsId
Section titled “Using inputsId”The Command’s command or script pulls its values from a separate Inputs block.
<Inputs id="repo-config">```yamlvariables: - name: OrgName type: string description: GitHub organization name - name: RepoName type: string description: Repository name\```</Inputs>
<Command id="create-repo" command="gh repo create {{ .OrgName }}/{{ .RepoName }} --private" inputsId="repo-config" title="Create GitHub Repository" successMessage="Repository {{ .RepoName }} created!" failMessage="Failed to create repository"/>Using Inline Inputs
Section titled “Using Inline Inputs”The Command collects input values directly. These values can be shared with other blocks, just like a standalone Inputs block.
<Command id="echo-message" command='echo "Hello, {{ .Name }}!"' title="Print Greeting"> <Inputs id="inline-greeting"> ```yaml variables: - name: Name type: string description: Your name validations: "required" \``` </Inputs></Command>Using Multiple inputsIds
Section titled “Using Multiple inputsIds”You can reference multiple Inputs blocks by passing an array of IDs. Variables are merged in order, with later IDs overriding earlier ones:
<Inputs id="lambda-config" templatePath="templates/lambda" />
<Inputs id="repo-config">```yamlvariables: - name: GithubOrgName type: string description: GitHub organization name - name: GithubRepoName type: string description: Repository name\```</Inputs>
<Command id="deploy-lambda" path="scripts/deploy.sh" inputsId={["lambda-config", "repo-config"]} title="Deploy Lambda Function" description="Deploy the Lambda function using variables from both inputs"/>In this example, the command has access to all variables from both lambda-config and repo-config. If both define a variable with the same name, the value from repo-config (the later ID) takes precedence.
Execution Context
Section titled “Execution Context”Scripts run in a persistent environment — environment variable changes (export, unset) and working directory changes (cd) carry forward to subsequent blocks. This lets you structure your runbook like a workflow where earlier steps set up the environment for later steps.
Scripts also run in a non-interactive shell, which means shell aliases (like ll) and shell functions (like nvm, rvm) are not available.
For full details, see Shell Execution Context.
Examples
Section titled “Examples”Let’s take a look at some example scripts:
Simple Deployment Script
Section titled “Simple Deployment Script”#!/bin/bashset -e # Exit on error
log_info "Starting deployment..."kubectl apply -f deployment.yamlkubectl rollout status deployment/myapp
log_info "Deployment complete!"Parameterized Script
Section titled “Parameterized Script”#!/bin/bashREGION="{{ .AwsRegion }}"VPC_NAME="{{ .VpcName }}"CIDR_BLOCK="{{ .CidrBlock }}"
log_info "Creating VPC $VPC_NAME in $REGION..."log_debug "CIDR block: $CIDR_BLOCK"
aws ec2 create-vpc \ --cidr-block "$CIDR_BLOCK" \ --tag-specifications "ResourceType=vpc,Tags=[{Key=Name,Value=$VPC_NAME}]" \ --region "$REGION"
log_info "VPC created successfully!"Script with Error Handling
Section titled “Script with Error Handling”#!/bin/bashset -e
function cleanup { log_info "Cleaning up..." # Cleanup code here}
trap cleanup EXIT
log_info "Running pre-deployment checks..."./check-prerequisites.sh || { log_error "Pre-checks failed"; exit 1; }
log_info "Deploying..."./deploy.sh
log_info "Running post-deployment validation..."./validate-deployment.sh || { log_error "Validation failed"; exit 1; }
log_info "Deployment successful!"Capturing Output Files
Section titled “Capturing Output Files”Commands can save files to the generated files directory using the $RUNBOOKS_OUTPUT environment variable. Any files written to this directory will automatically appear in the file panel after the command completes successfully.
Basic Example
Section titled “Basic Example”#!/bin/bash# Export OpenTofu outputs to generated filestofu output -json > "$RUNBOOKS_OUTPUT/tf-outputs.json"
# Copy a config filecp config.yaml "$RUNBOOKS_OUTPUT/"Or as an inline command:
<Command id="create-file" title="Create a greeting file" command={`echo "Hello from the command!" > "$RUNBOOKS_OUTPUT/greeting.txt"`} successMessage="File created successfully!"/>Organizing Files with Subdirectories
Section titled “Organizing Files with Subdirectories”You can create subdirectories within $RUNBOOKS_OUTPUT to organize your captured files:
#!/bin/bashmkdir -p "$RUNBOOKS_OUTPUT/terraform"mkdir -p "$RUNBOOKS_OUTPUT/config"
tofu output -json > "$RUNBOOKS_OUTPUT/opentofu/outputs.json"echo '{"env": "production"}' > "$RUNBOOKS_OUTPUT/config/settings.json"This creates:
generated/├── opentofu/│ └── outputs.json└── config/ └── settings.jsonHow It Works
Section titled “How It Works”- Before your script runs, Runbooks creates a temporary capture directory
- The
$RUNBOOKS_OUTPUTenvironment variable points to this directory - Your script writes files to
$RUNBOOKS_OUTPUT - After successful execution, files are copied to the generated files directory
- The temporary directory is cleaned up
Common Use Cases
Section titled “Common Use Cases”The <Command> block works especially well for mutating the world to a desired state. This could be either the user’s local environment, the company’s world, or the external world.
This might manifest as:
- Installing tools: Install tools needed to execute the runbook
- Configure environment: Configure the user’s environment
- Provisioning resources: Hit an API to provision resource.
- Deployments: Deploy applications or infrastructure to cloud environments
- Database Operations: Run migrations or seed data
- Build Steps: Compile code or build Docker images