github.com/hashicorp/packer@v1.14.3/website/content/docs/provisioners/shell-local.mdx (about)

     1  ---
     2  description: |
     3    The `shell-local` Packer provisioner runs shell scripts on the machine where Packer is running. Learn how to use the `shell-local` provisioner to run a shell script on your build server, desktop, or other local machine.
     4  page_title: shell-local provisioner reference
     5  ---
     6  
     7  <BadgesHeader>
     8    <PluginBadge type="official" />
     9  </BadgesHeader>
    10  
    11  # `shell-local` provisioner
    12  
    13  The `shell-local` provisioner runs shell scripts on the machine where
    14  Packer is running. Use the provisioner to run a shell script on your build server, desktop, or other local machine instead of the remote or guest machine you are 
    15  using Packer to provision.
    16  
    17  The [remote shell](/packer/docs/provisioners/shell) provisioner executes shell
    18  scripts on a remote machine.
    19  
    20  ## Basic Example
    21  
    22  The example below is fully functional.
    23  
    24  <Tabs>
    25  <Tab heading="HCL2">
    26  
    27  ```hcl
    28  source "file" "example" {
    29      content = "example content"
    30  }
    31  
    32  build {
    33    source "source.file.example" {
    34      target = "./test_artifact.txt"
    35    }
    36  
    37    provisioner "shell-local" {
    38      inline = ["echo foo"]
    39    }
    40  }
    41  ```
    42  
    43  </Tab>
    44  <Tab heading="JSON">
    45  
    46  ```json
    47  {
    48    "builders": [
    49      {
    50        "type": "file",
    51        "name": "example",
    52        "target": "./test_artifact.txt",
    53        "content": "example content"
    54      }
    55    ],
    56    "provisioners": [
    57      {
    58        "type": "shell-local",
    59        "inline": ["echo foo"]
    60      }
    61    ]
    62  }
    63  ```
    64  
    65  </Tab>
    66  </Tabs>
    67  
    68  ## Configuration Reference
    69  
    70  The reference of available configuration options is listed below. The only
    71  required element is `command`.
    72  
    73  Exactly _one_ of the following is required:
    74  
    75  - `command` (string) - This is a single command to execute. It will be
    76    written to a temporary file and run using the `execute_command` call below.
    77    If you are building a Windows VM on AWS, Azure, Google Compute, or OpenStack
    78    and would like to access the generated password that Packer uses to connect
    79    to the instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
    80    to set this as an environment variable.
    81  
    82  - `inline` (array of strings) - This is an array of commands to execute. The
    83    commands are concatenated by newlines and turned into a single file, so
    84    they are all executed within the same context. This allows you to change
    85    directories in one command and use something in the directory in the next
    86    and so on. Inline scripts are the easiest way to pull off simple tasks
    87    within the machine in which Packer is running.
    88  
    89  - `script` (string) - The path to a script to execute. This path can be
    90    absolute or relative. If it is relative, it is relative to the working
    91    directory when Packer is executed.
    92  
    93  - `scripts` (array of strings) - An array of scripts to execute. The scripts
    94    will be executed in the order specified. Each script is executed in
    95    isolation, so state such as variables from one script won't carry on to the
    96    next.
    97  
    98  Optional parameters:
    99  
   100  - `env` (map of strings) - A map of key/value pairs to inject prior to the
   101    execute_command. Packer injects some environmental variables by default into
   102    the environment, as well, which are covered in the section below. Duplicate
   103    `env` settings override `environment_vars` settings.
   104  
   105  - `environment_vars` (array of strings) - An array of key/value pairs to
   106    inject prior to the `execute_command`. The format should be `key=value`.
   107    Packer injects some environmental variables by default into the
   108    environment, as well, which are covered in the section below. If you are
   109    building a Windows VM on AWS, Azure, Google Compute, or OpenStack and would
   110    like to access the generated password that Packer uses to connect to the
   111    instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
   112    to set this as an environment variable. For example:
   113    `"environment_vars": "WINRMPASS={{.WinRMPassword}}"`
   114  
   115  - `env_var_format` (string) - When we parse the environment_vars that you
   116    provide, this gives us a string template to use in order to make sure that
   117    we are setting the environment vars correctly. By default on Windows hosts
   118    this format is `set %s=%s &&` and on Unix, it is `%s='%s'`. You probably
   119    won't need to change this format, but you can see usage examples for where
   120    it is necessary below.
   121  
   122  - `execute_command` (array of strings) - The command used to execute the
   123    script. By default this is `["/bin/sh", "-c", "{{.Vars}}", "{{.Script}}"]`
   124    on Unix and `["cmd", "/c", "{{.Vars}}", "{{.Script}}"]` on Windows. This is
   125    treated as a [template engine](/packer/docs/templates/legacy_json_templates/engine). There are two
   126    available variables: `Script`, which is the path to the script to run, and
   127    `Vars`, which is the list of `environment_vars`, if configured.
   128  
   129    If you choose to set this option, make sure that the first element in the
   130    array is the shell program you want to use (for example, "sh"), and a later
   131    element in the array must be `{{.Script}}`.
   132  
   133    This option provides you a great deal of flexibility. You may choose to
   134    provide your own shell program, for example "/usr/local/bin/zsh" or even
   135    "powershell.exe". However, with great power comes great responsibility -
   136    these commands are not officially supported and things like environment
   137    variables may not work if you use a different shell than the default.
   138  
   139    For backwards compatibility, you may also use `{{.Command}}`, but it is
   140    decoded the same way as `{{.Script}}`. We recommend using `{{.Script}}` for the
   141    sake of clarity, as even when you set only a single `command` to run,
   142    Packer writes it to a temporary file and then runs it as a script.
   143  
   144    If you are building a Windows VM on AWS, Azure, Google Compute, or OpenStack
   145    and would like to access the generated password that Packer uses to connect
   146    to the instance via WinRM, you can use the template variable `{{.WinRMPassword}}`
   147    to set this as an environment variable.
   148  
   149  - `inline_shebang` (string) - The
   150    [shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use
   151    when running commands specified by `inline`. By default, this is
   152    `/bin/sh -e`. If you're not using `inline`, then this configuration has no
   153    effect. **Important:** If you customize this, be sure to include something
   154    like the `-e` flag, otherwise individual steps failing won't fail the
   155    provisioner.
   156  
   157  - `only_on` (array of strings) - This is an array of [runtime operating
   158    systems](https://go.dev/doc/install/source#environment) where
   159    `shell-local` will execute. This allows you to execute `shell-local` _only_
   160    on specific operating systems. By default, shell-local will always run if
   161    `only_on` is not set."
   162  
   163  - `use_linux_pathing` (bool) - This is only relevant to Windows hosts. If you
   164    are running Packer in a Windows environment with the Windows Subsystem for
   165    Linux feature enabled, and would like to invoke a bash script rather than
   166    invoking a Cmd script, you'll need to set this flag to true; it tells
   167    Packer to use the Linux subsystem path for your script rather than the
   168    Windows path. (e.g. /mnt/c/path/to/your/file instead of
   169    C:/path/to/your/file). Please see the example below for more guidance on
   170    how to use this feature. If you are not on a Windows host, or you do not
   171    intend to use the shell-local provisioner to run a bash script, please
   172    ignore this option.
   173  
   174  - `valid_exit_codes` (list of ints) - Valid exit codes for the script. By
   175    default this is `0`.
   176  
   177  @include 'provisioners/common-config.mdx'
   178  
   179  ## Execute Command
   180  
   181  To many new users, the `execute_command` is puzzling. However, it provides an
   182  important function: customization of how the command is executed. The most
   183  common use case for this is dealing with **sudo password prompts**. You may
   184  also need to customize this if you use a non-POSIX shell, such as `tcsh` on
   185  FreeBSD.
   186  
   187  ### The Windows Linux Subsystem
   188  
   189  The shell-local provisioner was designed with the idea of allowing you to run
   190  commands in your local operating system's native shell. For Windows, we've
   191  assumed in our defaults that this is Cmd. However, it is possible to run a bash
   192  script as part of the Windows Linux Subsystem from the shell-local provisioner,
   193  by modifying the `execute_command` and the `use_linux_pathing` options in the
   194  provisioner config.
   195  
   196  The example below is a fully functional test config.
   197  
   198  One limitation of this offering is that "inline" and "command" options are not
   199  available to you; please limit yourself to using the "script" or "scripts"
   200  options instead.
   201  
   202  Please note that the WSL is a beta feature, and this tool is not guaranteed to
   203  work as you expect it to.
   204  
   205  <Tabs>
   206  <Tab heading="HCL2">
   207  
   208  ```hcl
   209  source "null" "example" {
   210      communicator = "none"
   211  }
   212  
   213  build {
   214      sources = [
   215          "source.null.example"
   216      ]
   217  
   218      provisioner "shell-local"{
   219          environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
   220          execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
   221          use_linux_pathing = true
   222          scripts = ["C:/Users/me/scripts/example_bash.sh"]
   223      }
   224      provisioner "shell-local"{
   225          environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
   226          execute_command = ["bash", "-c", "{{.Vars}} {{.Script}}"]
   227          use_linux_pathing = true
   228          script = "C:/Users/me/scripts/example_bash.sh"
   229      }
   230  }
   231  ```
   232  
   233  </Tab>
   234  <Tab heading="JSON">
   235  
   236  ```json
   237  {
   238    "builders": [
   239      {
   240        "type": "null",
   241        "communicator": "none"
   242      }
   243    ],
   244    "provisioners": [
   245      {
   246        "type": "shell-local",
   247        "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
   248        "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
   249        "use_linux_pathing": true,
   250        "scripts": ["C:/Users/me/scripts/example_bash.sh"]
   251      },
   252      {
   253        "type": "shell-local",
   254        "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
   255        "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
   256        "use_linux_pathing": true,
   257        "script": "C:/Users/me/scripts/example_bash.sh"
   258      }
   259    ]
   260  }
   261  ```
   262  
   263  </Tab>
   264  </Tabs>
   265  
   266  ## Default Environmental Variables
   267  
   268  In addition to being able to specify custom environmental variables using the
   269  `environment_vars` configuration, the provisioner automatically defines certain
   270  commonly useful environmental variables:
   271  
   272  - `PACKER_BUILD_NAME` is set to the name of the build that Packer is running.
   273    This is most useful when Packer is making multiple builds and you want to
   274    distinguish them slightly from a common provisioning script.
   275  
   276  - `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
   277    the machine that the script is running on. This is useful if you want to
   278    run only certain parts of the script on systems built with certain
   279    builders.
   280  
   281  - `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
   282    transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
   283    will be set to the address. You can use this address in your provisioner to
   284    download large files over HTTP. This may be useful if you're experiencing
   285    slower speeds using the default file provisioner. A file provisioner using
   286    the `winrm` communicator may experience these types of difficulties.
   287  
   288  ## Safely Writing A Script
   289  
   290  Whether you use the `inline` option, or pass it a direct `script` or `scripts`,
   291  it is important to understand a few things about how the `shell-local`
   292  provisioner works to run it safely and easily. This understanding will save you
   293  much time in the process.
   294  
   295  ### Once Per Builder
   296  
   297  The `shell-local` script(s) you pass are run once per builder. That means that
   298  if you have an `amazon-ebs` builder and a `docker` builder, your script will be
   299  run twice. If you have 3 builders, it will run 3 times, once for each builder.
   300  
   301  ### Always Exit Intentionally
   302  
   303  If any provisioner fails, the `packer build` stops and all interim artifacts
   304  are cleaned up.
   305  
   306  For a shell script, that means the script **must** exit with a zero code. You
   307  _must_ be extra careful to `exit 0` when necessary.
   308  
   309  ## Usage Examples:
   310  
   311  ### Windows Host
   312  
   313  Example of running a .cmd file on Windows:
   314  
   315  <Tabs>
   316  <Tab heading="HCL2">
   317  
   318  ```hcl
   319  provisioner "shell-local" {
   320    environment_vars = ["SHELLLOCALTEST=ShellTest1"]
   321    scripts          = ["./scripts/test_cmd.cmd"]
   322  }
   323  ```
   324  
   325  </Tab>
   326  <Tab heading="JSON">
   327  
   328  ```json
   329  {
   330    "type": "shell-local",
   331    "environment_vars": ["SHELLLOCALTEST=ShellTest1"],
   332    "scripts": ["./scripts/test_cmd.cmd"]
   333  }
   334  ```
   335  
   336  </Tab>
   337  </Tabs>
   338  
   339  Contents of "test_cmd.cmd":
   340  
   341      echo %SHELLLOCALTEST%
   342  
   343  Example of running an inline command on Windows: Required customization:
   344  tempfile_extension
   345  
   346  <Tabs>
   347  <Tab heading="HCL2">
   348  
   349  ```hcl
   350  provisioner "shell-local" {
   351    environment_vars   = ["SHELLLOCALTEST=ShellTest2"],
   352    tempfile_extension = ".cmd",
   353    inline             = [echo "%SHELLLOCALTEST%"]
   354  }
   355  ```
   356  
   357  </Tab>
   358  <Tab heading="JSON">
   359  
   360  ```json
   361  {
   362    "type": "shell-local",
   363    "environment_vars": ["SHELLLOCALTEST=ShellTest2"],
   364    "tempfile_extension": ".cmd",
   365    "inline": ["echo %SHELLLOCALTEST%"]
   366  }
   367  ```
   368  
   369  </Tab>
   370  </Tabs>
   371  
   372  Example of running a bash command on Windows using WSL: Required
   373  customizations: use_linux_pathing and execute_command
   374  
   375  <Tabs>
   376  <Tab heading="HCL2">
   377  
   378  ```hcl
   379  provisioner "shell-local" {
   380    environment_vars  = ["SHELLLOCALTEST=ShellTest3"],
   381    execute_command   = ["bash", "-c", "{{.Vars}} {{.Script}}"]
   382    use_linux_pathing = true
   383    script            = "./scripts/example_bash.sh"
   384  }
   385  ```
   386  
   387  </Tab>
   388  <Tab heading="JSON">
   389  
   390  ```json
   391  {
   392    "type": "shell-local",
   393    "environment_vars": ["SHELLLOCALTEST=ShellTest3"],
   394    "execute_command": ["bash", "-c", "{{.Vars}} {{.Script}}"],
   395    "use_linux_pathing": true,
   396    "script": "./scripts/example_bash.sh"
   397  }
   398  ```
   399  
   400  </Tab>
   401  </Tabs>
   402  
   403  Contents of `example_bash.sh`:
   404  
   405      #!/bin/bash
   406      echo $SHELLLOCALTEST
   407  
   408  Example of running a PowerShell script on Windows: Required customizations:
   409  `env_var_format` and `execute_command`
   410  
   411  <Tabs>
   412  <Tab heading="HCL2">
   413  
   414  ```hcl
   415  provisioner "shell-local" {
   416    environment_vars = ["SHELLLOCALTEST=ShellTest4"]
   417    execute_command  = ["powershell.exe", "{{.Vars}} {{.Script}}"]
   418    env_var_format   = "$env:%s=\"%s\"; "
   419    script           = "./scripts/example_ps.ps1"
   420  }
   421  ```
   422  
   423  </Tab>
   424  <Tab heading="JSON">
   425  
   426  ```json
   427  {
   428    "type": "shell-local",
   429    "environment_vars": ["SHELLLOCALTEST=ShellTest4"],
   430    "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
   431    "env_var_format": "$env:%s=\"%s\"; ",
   432    "script": "./scripts/example_ps.ps1"
   433  }
   434  ```
   435  
   436  </Tab>
   437  </Tabs>
   438  
   439  Example of running a PowerShell script on Windows as "inline": Required
   440  customizations: `env_var_format`, `tempfile_extension`, and `execute_command`
   441  
   442  <Tabs>
   443  <Tab heading="HCL2">
   444  
   445  ```hcl
   446  provisioner "shell-local" {
   447    tempfile_extension = ".ps1"
   448    environment_vars   = ["SHELLLOCALTEST=ShellTest5"]
   449    execute_command    = ["powershell.exe", "{{.Vars}} {{.Script}}"]
   450    env_var_format     = "$env:%s=\"%s\"; "
   451    inline             = ["write-output $env:SHELLLOCALTEST"]
   452  }
   453  ```
   454  
   455  </Tab>
   456  <Tab heading="JSON">
   457  
   458  ```json
   459  {
   460    "type": "shell-local",
   461    "tempfile_extension": ".ps1",
   462    "environment_vars": ["SHELLLOCALTEST=ShellTest5"],
   463    "execute_command": ["powershell.exe", "{{.Vars}} {{.Script}}"],
   464    "env_var_format": "$env:%s=\"%s\"; ",
   465    "inline": ["write-output $env:SHELLLOCALTEST"]
   466  }
   467  ```
   468  
   469  </Tab>
   470  </Tabs>
   471  
   472  ### Unix Host
   473  
   474  Example of running a Shell script on Unix:
   475  
   476  <Tabs>
   477  <Tab heading="HCL2">
   478  
   479  ```hcl
   480  provisioner "shell-local" {
   481    environment_vars = ["PROVISIONERTEST=ProvisionerTest1"]
   482    scripts          = ["./scripts/example_bash.sh"]
   483  }
   484  ```
   485  
   486  </Tab>
   487  <Tab heading="JSON">
   488  
   489  ```json
   490  {
   491    "type": "shell-local",
   492    "environment_vars": ["PROVISIONERTEST=ProvisionerTest1"],
   493    "scripts": ["./scripts/example_bash.sh"]
   494  }
   495  ```
   496  
   497  </Tab>
   498  </Tabs>
   499  
   500  Example of running a Shell script "inline" on Unix:
   501  
   502  <Tabs>
   503  <Tab heading="HCL2">
   504  
   505  ```hcl
   506  provisioner "shell-local" {
   507    environment_vars = ["PROVISIONERTEST=ProvisionerTest2"]
   508    inline           = ["echo hello", "echo $PROVISIONERTEST"]
   509  }
   510  
   511  ```
   512  
   513  </Tab>
   514  <Tab heading="JSON">
   515  
   516  ```json
   517  {
   518    "type": "shell-local",
   519    "environment_vars": ["PROVISIONERTEST=ProvisionerTest2"],
   520    "inline": ["echo hello", "echo $PROVISIONERTEST"]
   521  }
   522  ```
   523  
   524  </Tab>
   525  </Tabs>
   526  
   527  Example of running a Python script on Unix:
   528  
   529  <Tabs>
   530  <Tab heading="HCL2">
   531  
   532  ```hcl
   533  provisioner "shell-local" {
   534    script = "hello.py"
   535    environment_vars = ["HELLO_USER=packeruser"]
   536    execute_command  = [
   537      "/bin/sh",
   538      "-c",
   539      "{{.Vars}} /usr/local/bin/python {{.Script}}"
   540    ]
   541  }
   542  
   543  ```
   544  
   545  </Tab>
   546  <Tab heading="JSON">
   547  
   548  ```json
   549  {
   550    "type": "shell-local",
   551    "script": "hello.py",
   552    "environment_vars": ["HELLO_USER=packeruser"],
   553    "execute_command": [
   554      "/bin/sh",
   555      "-c",
   556      "{{.Vars}} /usr/local/bin/python {{.Script}}"
   557    ]
   558  }
   559  ```
   560  
   561  </Tab>
   562  </Tabs>
   563  
   564  ```text
   565  Where "hello.py" contains:
   566  
   567      import os
   568  
   569      print('Hello, %s!' % os.getenv("HELLO_USER"))
   570  ```