> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/run-step.md).

# Run step

Run scripts in a container image inside a containerized step group

The **Run** step runs scripts in a specific container image and shell.

Use the **Run** step for operations such as configuration scripts that apply settings for the deployment environment, or database migration scripts that handle schema changes required for the deployment.

Harness Continuous Delivery also includes a general scripting step, the [Shell Script](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md) step. The Shell Script step runs Bash or PowerShell and does not let you select a container.

This topic describes the **Run** step settings.

{% hint style="info" %}
**Permissions inheritance** When you run a **Run** step in a [containerized step group](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md), go to [Harness permissions inheritance logic](/continuous-delivery/troubleshooting-and-resources/knowledge-base-article/configuration-inheritance-stepgroup-step.md) to review how permissions are inherited.
{% endhint %}

***

## What you will learn from this topic <a href="#what-will-you-learn-in-this-topic" id="what-will-you-learn-in-this-topic"></a>

* How to set the [container registry and image](#container-registry-and-image) for the step
* How to define the [shell and command](#shell-and-command) to run
* How to configure [environment variables](#environment-variables) and [output variables](#output-variables)
* How to set [privileged](#privileged) mode, the [image pull policy](#image-pull-policy), and [container resources](#set-container-resources) so the script runs in the selected image

***

## Before you begin

Review the following setup before you add a **Run** step:

* **Containerized step group**: The **Run** step runs inside a containerized step group. Go to [Containerize step groups](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md) to enable container-based execution.
* **Shell without a container**: Go to [Shell Script step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md) to run Bash or PowerShell without selecting a container image.
* **Permission inheritance**: Go to [Harness permissions inheritance logic](/continuous-delivery/troubleshooting-and-resources/knowledge-base-article/configuration-inheritance-stepgroup-step.md) to review how a step inherits permissions from its step group.

***

## Container Registry and Image <a href="#container-registry-and-image" id="container-registry-and-image"></a>

The **Run** step runs your commands inside a container image. When the **Run** step is inside a [containerized step group](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md) with container-based execution enabled, the **Registry Type** setting controls where Harness pulls the container image from. Two options are supported:

* **Artifact Registry**: Pull the image directly from a Harness Artifact Registry, without a Docker connector.
* **Third-Party Artifact Registry**: Pull the image from an external Docker registry through a Harness Docker connector. This is the default option.

### Artifact Registry <a href="#artifact-registry" id="artifact-registry"></a>

Select **Artifact Registry** as the **Registry Type** to pull the image directly from a Harness Artifact Registry. You do not need a Docker connector.

* In **Container Registry**, select the Harness Artifact Registry that hosts the image.
* In **Image**, enter the image reference in the `imageName:tag` format, such as `myapp:1.2.3`.

### Third-Party Container Registry <a href="#third-party-container-registry" id="third-party-container-registry"></a>

The **Container Registry** field is a Harness Docker registry connector for the image that you want Harness to run commands in, such as an image hosted on Docker Hub.

The **Image** field is the fully qualified name (FQN) or artifact name of the Docker image to use when this step runs commands. For example, `us.gcr.io/<project-id>/quickstart-image`. The image name should include the tag. If you do not include a tag, Harness uses the `latest` tag.

You can use any Docker image from any Docker registry, including private registries. Different container registries require different name formats:

* **Docker Registry**: Enter the name of the artifact you want to use, such as `library/tomcat`. Wildcards are not supported. An FQN is required for images in private container registries.
* **ECR**: Enter the fully qualified name (FQN) of the artifact that you want to use. Images stored in repositories must reference a path. For example: `<aws-account-id>.dkr.ecr.us-east-1.amazonaws.com/todolist:0.2`.
* **GCR**: Enter the fully qualified name (FQN) of the artifact that you want to use. Images stored in repositories must reference a path that starts with the project ID where the artifact is stored. For example: `us.gcr.io/<project-id>/quickstart-image:latest`.

![GCR Container Registry and Image settings](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-a368eab5812aab1c7d0fe5892dd9342f568d3686%2F659f371c3e8d30d831642c9fef9dbf652dca4c5fd050f0dc68b128f0b04101d9.png?alt=media)

{% hint style="warning" %}
**Google Container Registry deprecation**

Google Container Registry (GCR) is being deprecated. Go to [Google Container Registry (GCR)](/continuous-delivery/use-continuous-delivery/cd-building-blocks/services/artifact-sources.md#google-container-registry-gcr) to review the deprecation notice.
{% endhint %}

***

## Shell and Command <a href="#shell-and-command" id="shell-and-command"></a>

Use **Shell** and **Command** to define the commands that you need to run in this step.

For **Shell**, select the shell script type. Options include **Bash**, **PowerShell**, **Pwsh**, **Sh**, and **Python**. If the step includes commands that are not supported for the selected shell type, the step fails.

The binaries required by the script must be available on the infrastructure running the step or in the image specified in **Container Registry** and **Image**.

In **Command**, enter [POSIX](https://en.wikipedia.org/wiki/POSIX) shell script commands for this step. The commands run inside the container.

{% hint style="info" %}
**Background step Id**

You can reference services started in Continuous Delivery [Background steps](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/background-step.md) by using the Background step **Id** in the **Run** step **Command**. For example, a cURL command can call `STEPGROUPID_BACKGROUNDSTEPID:5000` where it might otherwise call `localhost:5000`.

<img src="https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-2de4864202cae4091b45dd38baeec01d6ac14357%2F1d52c641a8b442054d83fc2b8bacc1917371f53c7100a0fcf0a7b6666342ce2e.png?alt=media" alt="The Background step Id, pythonscript, used in a cURL command in a Run step" data-size="original">

You must include the step group Id, such as `curl STEPGROUPID_BACKGROUNDSTEPID:5000`, even if both steps are in the same step group.
{% endhint %}

Select each tab below to view an example for each shell type.

{% tabs %}
{% tab title="Bash" %}
This Bash script example checks the Java version.

```yaml
              - step:
                  ...
                  spec:
                    shell: Bash
                    command: |-
                      JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
                      if [[ $JAVA_VER == 17 ]]; then
                        echo successfully installed $JAVA_VER
                      else
                        exit 1
                      fi
```

{% endtab %}

{% tab title="PowerShell" %}
This PowerShell example runs `Wait-Event`.

```yaml
              - step:
                  ...
                  spec:
                    shell: Powershell
                    command: Wait-Event -SourceIdentifier "ProcessStarted"
```

{% endtab %}

{% tab title="Pwsh" %}
This PowerShell Core example runs `ForEach-Object` over a list of events.

```yaml
              - step:
                  ...
                  spec:
                    shell: Pwsh
                    command: |-
                      $Events = Get-EventLog -LogName System -Newest 1000
                      $events | ForEach-Object -Begin {Get-Date} -Process {Out-File -FilePath Events.txt -Append -InputObject $_.Message} -End {Get-Date}
```

{% hint style="info" %}
**PowerShell Core**

You can run PowerShell Core commands in pods or containers that have `pwsh` installed.
{% endhint %}
{% endtab %}

{% tab title="Sh" %}
In this example, Harness pulls a `python` image and runs a shell script (`Sh`) that runs `pytest` with code coverage.

```yaml
              - step:
                  ...
                  spec:
                    connectorRef: account.harnessImage
                    image: python:latest
                    shell: Sh
                    command: |-
                      echo "Welcome to Harness CI"
                      uname -a
                      pip install pytest
                      pip install pytest-cov
                      pip install -r requirements.txt

                      pytest -v --cov --junitxml="result.xml" test_api.py test_api_2.py test_api_3.py
```

{% endtab %}

{% tab title="Python" %}
If the `shell` is `Python`, supply Python commands directly in `command`.

This example uses a basic `print` command.

```yaml
            steps:
              - step:
                  ...
                  spec:
                    shell: Python
                    command: print('Hello, world!')
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Declare output variables**

If your script produces an output variable, you must declare the output variable in the **Run** step [Output Variables](#output-variables). For example, the following step runs a Python script that defines an output variable called `OS_VAR`, and `OS_VAR` is also declared in `outputVariables`.

```yaml
              - step:
                  type: Run
                  name: Run_2
                  identifier: Run_2
                  spec:
                    shell: Python
                    command: |-
                      import os
                      os.environ["OS_VAR"] = value
                    outputVariables:
                      - name: OS_VAR
```

{% endhint %}

***

## Privileged <a href="#privileged" id="privileged"></a>

Enable this option to run the container with escalated privileges. This is equivalent to running a container with the Docker `--privileged` flag.

***

## Report paths <a href="#report-paths" id="report-paths"></a>

Specify one or more paths to files that store information in JUnit XML format. You can add multiple paths. If you specify multiple paths, the files must contain unique information to avoid duplicates. [Glob](https://en.wikipedia.org/wiki/Glob_\(programming\)) is supported.

***

## Environment variables <a href="#environment-variables" id="environment-variables"></a>

You can inject environment variables into a container and use them in the **Command** script. You must enter a **Name** and **Value** for each variable.

You can reference environment variables in the **Command** script by their name. For example, a Bash script uses `$var_name` or `${var_name}`, and a Windows PowerShell script uses `$Env:varName`.

Variable values can be [fixed values, runtime inputs, and expressions](https://developer.harness.io/docs/platform/variables-and-expressions/runtime-inputs). For example, if the value type is expression, you can enter a value that references the value of another setting in the stage or pipeline.

***

## Output variables <a href="#output-variables" id="output-variables"></a>

Output variables expose values for use by other steps or stages later in the pipeline.

<details>

<summary>YAML example: Output variable</summary>

In the following YAML example, step `alpha` exports an output variable called `myVar`, and then step `beta` references that output variable.

```yaml
              - step:
                  type: Run
                  name: alpha
                  identifier: alpha
                  spec:
                    shell: Sh
                    command: export myVar=varValue
                    outputVariables:
                      - name: myVar
              - step:
                  type: Run
                  name: beta
                  identifier: beta
                  spec:
                    shell: Sh
                    command: |-
                      echo <+steps.alpha.output.outputVariables.myVar>
                      echo <+execution.steps.alpha.output.outputVariables.myVar>
```

</details>

{% hint style="warning" %}
**Secrets in output variables**

If an output variable value contains a secret, the secret is visible in the following areas of the pipeline execution:

* On the **Output** tab of the step where the output variable originates.
* In the step logs for any later steps that reference that variable.

Go to [Secrets and log sanitization](https://developer.harness.io/docs/platform/secrets/secrets-management/secrets-and-log-sanitization/) to review how Harness handles secrets in logs and outputs.
{% endhint %}

### Create an output variable <a href="#create-an-output-variable" id="create-an-output-variable"></a>

Perform the following steps to create an output variable in the step where it originates:

1. In **Command**, export the output variable. For example, the following command exports a variable called `myVar` with a value of `varValue`:

   ```bash
   export myVar=varValue
   ```
2. In the same step's **Output Variables**, declare the variable name, such as `myVar`.

### Reference an output variable <a href="#reference-an-output-variable" id="reference-an-output-variable"></a>

To reference an output variable in a later step or stage in the same pipeline, use a variable [expression](https://developer.harness.io/docs/platform/variables-and-expressions/runtime-inputs#expressions) that includes the originating step's Id and the variable name.

Use either of the following expressions to reference an output variable in another step in the same stage:

```
<+steps.STEP_ID.output.outputVariables.VAR_NAME>
<+execution.steps.STEP_GROUP_ID.steps.STEP_ID.output.outputVariables.VAR_NAME>
```

To reference an output variable in a stage other than the one where the output variable originated, use either of the following expressions:

```
<+stages.STAGE_ID.spec.execution.steps.STEP_ID.output.outputVariables.VAR_NAME>
<+pipeline.stages.STAGE_ID.spec.execution.steps.STEP_GROUP_ID.steps.STEP_ID.output.outputVariables.VAR_NAME>
```

### Scope output variables with aliases <a href="#scoping-output-variables-using-aliases" id="scoping-output-variables-using-aliases"></a>

To prevent variable name conflicts, you can use **Publish Variable Names (Alias)** to scope output variables to different entities.

Perform the following steps to scope an output variable with an alias:

1. **Export the variables**: Use **Output Variables** to export the variables.
2. **Define an alias**: In **Publish Variable Names (Alias)**, enter an alias to use when you reference the exported output variables.
3. **Select a scope**: In **Scope**, select the scope for the exported output variable.

The following screenshot shows the output alias configured with **Stage** scope:

![Stage-scoped output alias configuration](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-74fe370a3565b6309e5f2c3cf201ba7c6ba3ca19%2Fstage-output-vars.png?alt=media)

The following screenshot shows the output alias configured with **Pipeline** scope:

![Pipeline-scoped output alias configuration](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-a0fd90866d260269b201a0adfee3bd7af8233874%2Fpipeline-output-vars.png?alt=media)

You can scope output variables to the following entities:

* **Step group**:
  * The output variable must be used in the same step group, including nested child step groups.
  * The format for referencing an exported step group output variable using its alias is:

    ```
    <+exportedVariables.getValue("stepGroup.ALIAS_NAME.OUTPUT_VARIABLE_NAME")>
    ```
* **Stage**:
  * The output variable can be used anywhere in the same stage, including step groups in the same stage. It cannot be used outside the same stage.
  * The format for referencing an exported stage output variable using its alias is:

    ```
    <+exportedVariables.getValue("stage.ALIAS_NAME.OUTPUT_VARIABLE_NAME")>
    ```
* **Pipeline**:
  * The output variable can be used anywhere in the same pipeline, but not in a [chained pipeline](https://developer.harness.io/docs/platform/pipelines/pipeline-chaining).
  * The format for referencing an exported pipeline output variable using its alias is:

    ```
    <+exportedVariables.getValue("pipeline.ALIAS_NAME.OUTPUT_VARIABLE_NAME")>
    ```

To reference a map of exported output variables, reference the alias in the format `<+exportedVariables.getValue("SCOPE.ALIAS_NAME")>`, such as `<+exportedVariables.getValue("stepGroup.info")>`.

{% hint style="info" %}
**Limits for exported variables**

* Exported variables are immutable.
* Variables cannot be exported in looping strategies.
* Exported variables are not supported in pipeline chaining.
* All output variables are exported. You cannot select a subset.
  {% endhint %}

<details>

<summary>Step group scope pipeline example</summary>

```yaml
pipeline:
  projectIdentifier: myproject
  orgIdentifier: default
  tags: {}
  stages:
    - stage:
        identifier: testSimple
        type: Custom
        name: testSimple
        description: ""
        spec:
          execution:
            steps:
              - stepGroup:
                  identifier: stepGroup1
                  name: stepGroup1
                  steps:
                    - step:
                        identifier: Run_1
                        type: Run
                        name: Run_1
                        spec:
                          shell: Bash
                          command: |-
                            export var1="val1"
                            export var2="val2"
                          outputVariables:
                            - name: var1
                            - name: var2
                          outputAlias:
                            key: info
                            scope: StepGroup
                        timeout: 10m
                    - step:
                        type: Run
                        name: outputs
                        identifier: outputs
                        spec:
                          shell: Bash
                          command: |-
                            echo "reference using aliases:"

                            echo "var1:" <+exportedVariables.getValue("stepGroup.info.var1")>
                            echo "var2:" <+exportedVariables.getValue("stepGroup.info.var2")>
                            echo "var map:" <+exportedVariables.getValue("stepGroup.info")>

                            echo "reference using standard output exp:"

                            echo "var1:" <+pipeline.stages.testSimple.spec.execution.steps.stepGroup1.steps.Run_1.output.outputVariables.var1>
                            echo "var2:" <+pipeline.stages.testSimple.spec.execution.steps.stepGroup1.steps.Run_1.output.outputVariables.var2>
                          outputVariables: []
                        timeout: 10m
        tags: {}
  identifier: StepGroupExport
  name: StepGroupExport
```

</details>

Go to [Scoping output variables using aliases](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md#scoping-output-variables-using-aliases) in the Shell Script step topic to review more examples.

***

## Image pull policy <a href="#image-pull-policy" id="image-pull-policy"></a>

Select an option to set the pull policy for the image:

* **Always**: The kubelet queries the container image registry to resolve the name to an image digest every time the kubelet launches a container. If the kubelet encounters an exact digest cached locally, it uses its cached image; otherwise, the kubelet downloads (pulls) the image with the resolved digest, and uses that image to launch the container.
* **If Not Present**: The image is pulled only if it is not already present locally.
* **Never**: The image is assumed to exist locally. No attempt is made to pull the image.

***

## Run as user <a href="#run-as-user" id="run-as-user"></a>

You can define the UID to run all policies within the pod. Go to [Security context for a pod](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod) to review the Kubernetes security context, and go to [Harness permissions inheritance logic](/continuous-delivery/troubleshooting-and-resources/knowledge-base-article/configuration-inheritance-stepgroup-step.md) to review permission inheritance when you use containerized step groups.

***

## Set container resources <a href="#set-container-resources" id="set-container-resources"></a>

Set the resource limits and requests for the container's CPU and memory. Go to [Manage resource containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container) to review CPU and memory limits and requests.

{% hint style="info" %}
**Feature flag**

The ability to set resource requests requires the feature flag `CI_SUPPORT_RESOURCE_REQUESTS`. To enable it, contact [Harness Support](mailto:support@harness.io).
{% endhint %}

Define the resource limits and requests by using the units defined by Kubernetes. Go to [Resource units in Kubernetes](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes) to review the units.

If you use a **Run** step in a step group and define resources with variables, the variables must be at the stage or pipeline level. Step group variables are not evaluated at the correct time when the resource is launched.

***

## Hidden or invisible characters <a href="#hidden-or-invisible-characters" id="hidden-or-invisible-characters"></a>

You might experience unexplained behavior in your scripts because of hidden or invisible characters. These characters often appear when you paste from non-plain-text sources, and they can cause errors in how the script operates. Harness displays invisible characters, and this display is enabled by default.

You see a highlighted space within your scripts when an invisible character is present:

![Highlighted invisible character in a script](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-fbed49ef0a7f53bc55a524de5e9f73045589d889%2Finvisiblechr-01.png?alt=media)

Hover over the highlight and select `adjust settings` to identify the character:

![Hover over the highlight to view the invisible character](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-596f267a8dbc14c7b9cf8acf401cb57bd95159ad%2Finvisiblechr-hover.png?alt=media)

If you make a selection accidentally, right-click within the script space and select the `Command Palette` to make adjustments:

![Open the Command Palette from the script space](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-0ce687ee388337907d8f0bcb6b248b2a067448db%2Finvisiblechr-cmdplt.png?alt=media)

A dialog box appears where you can search for the option that controls how highlighting is set:

![Toggle invisible character highlighting settings](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-e9b47e6db907353ab9521c956fd4702690d8965b%2Finvisiblechr-toggle.png?alt=media)

***

## Advanced settings <a href="#advanced-settings" id="advanced-settings"></a>

On the **Advanced** tab, you can use the following options:

* [Conditional Execution](https://developer.harness.io/docs/platform/pipelines/step-skip-condition-settings)
* [Failure Strategy](https://developer.harness.io/docs/platform/pipelines/failure-handling/define-a-failure-strategy-on-stages-and-steps)
* [Looping Strategy](https://developer.harness.io/docs/platform/pipelines/looping-strategies/looping-strategies-matrix-repeat-and-parallelism)
* [Policy Enforcement](https://developer.harness.io/docs/platform/governance/policy-as-code/harness-governance-overview)

***

## Next steps <a href="#next-steps" id="next-steps"></a>

* Go to [Shell Script step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/utilities/shell-script-step.md) to run a Bash or PowerShell script without selecting a container.
* Go to [Background step](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/background-step.md) to start a service that the **Run** step can call.
* Go to [Containerize step groups](/continuous-delivery/use-continuous-delivery/cd-building-blocks/cd-steps/containerized-steps/containerized-step-groups.md) to configure the step group that runs the **Run** step in a container.
* Go to [Define failure strategies for stages and steps](https://developer.harness.io/docs/platform/pipelines/failure-handling/define-a-failure-strategy-on-stages-and-steps) to configure what happens if the script fails.

{% @harness-feedback/feedback %}
