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

     1  ---
     2  description: |
     3    The `shell` Packer provisioner runs shell scripts on the machine Packer builds. Use the `shell` provisioner to install and configure software on a machine.
     4  page_title: shell provisioner reference
     5  ---
     6  
     7  <BadgesHeader>
     8    <PluginBadge type="official" />
     9  </BadgesHeader>
    10  
    11  # `shell` provisioner
    12  
    13  The `shell` Packer provisioner runs shell scripts on the machine Packer builds. Use the `shell` provisioner to install and configure software on a machine.
    14  
    15  -> **Building Windows images?** You probably want to use the
    16  [PowerShell](/packer/docs/provisioners/powershell) or [Windows
    17  Shell](/packer/docs/provisioners/windows-shell) provisioners.
    18  
    19  ## Basic Example
    20  
    21  The example below is fully functional.
    22  
    23  <Tabs>
    24  <Tab heading="HCL2">
    25  
    26  ```hcl
    27  provisioner "shell" {
    28      inline = ["echo foo"]
    29  }
    30  ```
    31  
    32  </Tab>
    33  <Tab heading="JSON">
    34  
    35  ```json
    36  {
    37    "type": "shell",
    38    "inline": ["echo foo"]
    39  }
    40  ```
    41  
    42  </Tab>
    43  </Tabs>
    44  
    45  ## Configuration Reference
    46  
    47  @include 'provisioners/shell-config.mdx'
    48  
    49  - `env` (map of strings) - A map of key/value pairs to inject prior to the
    50    execute_command. Packer injects some environmental variables by default into
    51    the environment, as well, which are covered in the section below. Duplicate
    52    `env` settings override `environment_vars` settings.
    53  
    54  - `environment_vars` (array of strings) - An array of key/value pairs to
    55    inject prior to the execute_command. The format should be `key=value`.
    56    Packer injects some environmental variables by default into the
    57    environment, as well, which are covered in the section below.
    58  
    59  - `env_var_format` (string) - When we parse the environment_vars that you
    60    provide, this gives us a string template to use in order to make sure that
    61    we are setting the environment vars correctly. By default it is `"%s='%s' "`.
    62    When used in conjunction with `use_env_var_file` the default is `"export %s='%s'\n"`
    63  
    64  - `use_env_var_file` (boolean) - If true, Packer will write your environment
    65    variables to a tempfile and source them from that file, rather than
    66    declaring them inline in our execute_command. The default
    67    `execute_command` will be
    68    `chmod +x {{.Path}}; . {{.EnvVarFile}} && {{.Path}}`. This option is
    69    unnecessary for most cases, but if you have extra quoting in your custom
    70    `execute_command`, then this may be required for proper script
    71    execution. Default: `false`.
    72  
    73  - `execute_command` (string) - The command to use to execute the script. By
    74    default this is `chmod +x {{ .Path }}; {{ .Vars }} {{ .Path }}`, unless the
    75    user has set `"use_env_var_file": true` -- in that case, the default
    76    `execute_command` is `chmod +x {{.Path}}; . {{.EnvVarFile}} && {{.Path}}`.
    77    This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you may
    78    use user variables and template functions in this field. In addition, there
    79    are three available extra variables:
    80  
    81    - `Path` is the path to the script to run
    82    - `Vars` is the list of `environment_vars`, if configured.
    83    - `EnvVarFile` is the path to the file containing env vars, if
    84      `use_env_var_file` is true.
    85  
    86  - `expect_disconnect` (boolean) - Defaults to `false`. When `true`, allow the
    87    server to disconnect from Packer without throwing an error. A disconnect
    88    might happen if you restart the SSH server or reboot the host.
    89  
    90  - `inline_shebang` (string) - The
    91    [shebang](https://en.wikipedia.org/wiki/Shebang_%28Unix%29) value to use
    92    when running commands specified by `inline`. By default, this is
    93    `/bin/sh -e`. If you're not using `inline`, then this configuration has no
    94    effect. **Important:** If you customize this, be sure to include something
    95    like the `-e` flag, otherwise individual steps failing won't fail the
    96    provisioner.
    97  
    98  - `remote_folder` (string) - The folder where the uploaded script will reside
    99    on the machine. This defaults to `/tmp`.
   100  
   101  - `remote_file` (string) - The filename the uploaded script will have on the
   102    machine. This defaults to `script_nnn.sh`.
   103  
   104  - `remote_path` (string) - The full path to the uploaded script will have on
   105    the machine. By default this is `remote_folder/remote_file`, if set this
   106    option will override both `remote_folder` and `remote_file`.
   107  
   108  - `skip_clean` (boolean) - If true, specifies that the helper scripts
   109    uploaded to the system will not be removed by Packer. This defaults to
   110    `false` (clean scripts from the system).
   111  
   112  - `start_retry_timeout` (string) - The amount of time to attempt to _start_
   113    the remote process. By default this is `5m` or 5 minutes. This setting
   114    exists in order to deal with times when SSH may restart, such as a system
   115    reboot. Set this to a higher value if reboots take a longer amount of time.
   116  
   117  - `pause_after` (string) - Wait the amount of time after provisioning a shell
   118    script, this pause be taken if all previous steps were successful.
   119  
   120  @include 'provisioners/common-config.mdx'
   121  
   122  ## Execute Command Example
   123  
   124  To many new users, the `execute_command` is puzzling. However, it provides an
   125  important function: customization of how the command is executed. The most
   126  common use case for this is dealing with **sudo password prompts**. You may
   127  also need to customize this if you use a non-POSIX shell, such as `tcsh` on
   128  FreeBSD.
   129  
   130  ### Sudo Example
   131  
   132  Some operating systems default to a non-root user. For example if you login as
   133  `ubuntu` and can sudo using the password `packer`, then you'll want to change
   134  `execute_command` to be:
   135  
   136  ```text
   137  "echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'"
   138  ```
   139  
   140  The `-S` flag tells `sudo` to read the password from stdin, which in this case
   141  is being piped in with the value of `packer`.
   142  
   143  The above example won't work if your environment vars contain spaces or single
   144  quotes; in these cases try removing the single quotes:
   145  
   146  ```text
   147  "echo 'packer' | sudo -S env {{ .Vars }} {{ .Path }}"
   148  ```
   149  
   150  By setting the `execute_command` to this, your script(s) can run with root
   151  privileges without worrying about password prompts.
   152  
   153  ### FreeBSD Example
   154  
   155  FreeBSD's default shell is `tcsh`, which deviates from POSIX semantics. In
   156  order for packer to pass environment variables you will need to change the
   157  `execute_command` to:
   158  
   159  ```text
   160  chmod +x {{ .Path }}; env {{ .Vars }} {{ .Path }}
   161  ```
   162  
   163  Note the addition of `env` before `{{ .Vars }}`.
   164  
   165  ## Default Environmental Variables
   166  
   167  In addition to being able to specify custom environmental variables using the
   168  `environment_vars` configuration, the provisioner automatically defines certain
   169  commonly useful environmental variables:
   170  
   171  - `PACKER_BUILD_NAME` is set to the [name of the
   172    build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running.
   173    This is most useful when Packer is making multiple builds and you want to
   174    distinguish them slightly from a common provisioning script.
   175  
   176  - `PACKER_BUILDER_TYPE` is the type of the builder that was used to create
   177    the machine that the script is running on. This is useful if you want to
   178    run only certain parts of the script on systems built with certain
   179    builders.
   180  
   181  - `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file
   182    transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this
   183    will be set to the address. You can use this address in your provisioner to
   184    download large files over HTTP. This may be useful if you're experiencing
   185    slower speeds using the default file provisioner. A file provisioner using
   186    the `winrm` communicator may experience these types of difficulties.
   187  
   188  ## Handling Reboots
   189  
   190  Provisioning sometimes involves restarts, usually when updating the operating
   191  system. Packer is able to tolerate restarts via the shell provisioner.
   192  
   193  Packer handles this by retrying to start scripts for a period of time before
   194  failing. This allows time for the machine to start up and be ready to run
   195  scripts. The amount of time the provisioner will wait is configured using
   196  `start_retry_timeout`, which defaults to a few minutes.
   197  
   198  Sometimes, when executing a command like `reboot`, the shell script will return
   199  and Packer will start executing the next one before SSH actually quits and the
   200  machine restarts. For this, use `pause_before` to make Packer wait before
   201  executing the next script:
   202  
   203  <Tabs>
   204  <Tab heading="HCL2">
   205  
   206  ```hcl
   207  provisioner "shell" {
   208    script       = "script.sh"
   209    pause_before = "10s"
   210    timeout      = "10s"
   211  }
   212  ```
   213  
   214  </Tab>
   215  <Tab heading="JSON">
   216  
   217  ```json
   218  {
   219    "type": "shell",
   220    "script": "script.sh",
   221    "pause_before": "10s",
   222    "timeout": "10s"
   223  }
   224  ```
   225  
   226  </Tab>
   227  </Tabs>
   228  
   229  Some OS configurations don't properly kill all network connections on reboot,
   230  causing the provisioner to hang despite a reboot occurring. In this case, make
   231  sure you shut down the network interfaces on reboot or in your shell script.
   232  For example, on Gentoo:
   233  
   234  ```text
   235  /etc/init.d/net.eth0 stop
   236  ```
   237  
   238  ## SSH Agent Forwarding
   239  
   240  Some provisioning requires connecting to remote SSH servers from within the
   241  packer instance. The below example is for pulling code from a private git
   242  repository utilizing openssh on the client. Make sure you are running
   243  `ssh-agent` and add your git repo SSH keys into it using
   244  `ssh-add /path/to/key`. When the Packer instance needs access to the SSH keys
   245  the agent will forward the request back to your `ssh-agent`.
   246  
   247  Note: when provisioning via git you should add the git server keys into the
   248  `~/.ssh/known_hosts` file otherwise the git command could hang awaiting input.
   249  This can be done by copying the file in via the [file
   250  provisioner](/packer/docs/provisioners/file) (more secure) or using `ssh-keyscan`
   251  to populate the file (less secure). An example of the latter accessing github
   252  would be:
   253  
   254  <Tabs>
   255  <Tab heading="HCL2">
   256  
   257  ```hcl
   258  provisioner "shell" {
   259    inline = [
   260      "sudo apt-get install -y git",
   261      "ssh-keyscan github.com >> ~/.ssh/known_hosts",
   262      "git clone git@github.com:exampleorg/myprivaterepo.git"
   263    ]
   264  }
   265  ```
   266  
   267  </Tab>
   268  <Tab heading="JSON">
   269  
   270  ```json
   271  {
   272    "type": "shell",
   273    "inline": [
   274      "sudo apt-get install -y git",
   275      "ssh-keyscan github.com >> ~/.ssh/known_hosts",
   276      "git clone git@github.com:exampleorg/myprivaterepo.git"
   277    ]
   278  }
   279  ```
   280  
   281  </Tab>
   282  </Tabs>
   283  
   284  ## Troubleshooting
   285  
   286  _My shell script doesn't work correctly on Ubuntu_
   287  
   288  - On Ubuntu, the `/bin/sh` shell is
   289    [dash](https://en.wikipedia.org/wiki/Debian_Almquist_shell). If your script
   290    has [bash](<https://en.wikipedia.org/wiki/Bash_(Unix_shell)>)-specific
   291    commands in it, then put `#!/bin/bash -e` at the top of your script.
   292    Differences between dash and bash can be found on the
   293    [DashAsBinSh](https://wiki.ubuntu.com/DashAsBinSh) Ubuntu wiki page.
   294  
   295  _My shell works when I login but fails with the shell provisioner_
   296  
   297  - See the above tip. More than likely, your login shell is using `/bin/bash`
   298    while the provisioner is using `/bin/sh`.
   299  
   300  _My installs hang when using `apt-get` or `yum`_
   301  
   302  - Make sure you add a `-y` to the command to prevent it from requiring user
   303    input before proceeding.
   304  
   305  _How do I tell what my shell script is doing?_
   306  
   307  - Adding a `-x` flag to the shebang at the top of the script (`#!/bin/sh -x`)
   308    will echo the script statements as it is executing.
   309  
   310  _My builds don't always work the same_
   311  
   312  - Some distributions start the SSH daemon before other core services which
   313    can create race conditions. Your first provisioner can tell the machine to
   314    wait until it completely boots.
   315  
   316  <Tabs>
   317  <Tab heading="HCL2">
   318  
   319  ```hcl
   320  provisioner "shell" {
   321    inline = ["sleep 10"]
   322  }
   323  ```
   324  
   325  </Tab>
   326  <Tab heading="JSON">
   327  
   328  ```json
   329  {
   330    "type": "shell",
   331    "inline": ["sleep 10"]
   332  }
   333  ```
   334  
   335  </Tab>
   336  </Tabs>
   337  
   338  ## Quoting Environment Variables
   339  
   340  Packer manages quoting for you, so you shouldn't have to worry about it. Below
   341  is an example of Packer template inputs and what you should expect to get out:
   342  
   343  <Tabs>
   344  <Tab heading="HCL2">
   345  
   346  ```hcl
   347  provisioner "shell" {
   348    environment_vars = [
   349      "FOO=foo",
   350      "BAR=bar's",
   351      "BAZ=baz=baz",
   352      "QUX==qux",
   353      "FOOBAR=foo bar",
   354      "FOOBARBAZ='foo bar baz'",
   355      "QUX2=\"qux\""
   356    ]
   357    inline = [
   358      "echo \"FOO is $FOO\"",
   359      "echo \"BAR is $BAR\"",
   360      "echo \"BAZ is $BAZ\"",
   361      "echo \"QUX is $QUX\"",
   362      "echo \"FOOBAR is $FOOBAR\"",
   363      "echo \"FOOBARBAZ is $FOOBARBAZ\"",
   364      "echo \"QUX2 is $QUX2\""
   365    ]
   366  }
   367  ```
   368  
   369  </Tab>
   370  <Tab heading="JSON">
   371  
   372  ```json
   373  "provisioners": [
   374    {
   375      "type":  "shell",
   376      "environment_vars": ["FOO=foo",
   377                           "BAR=bar's",
   378                           "BAZ=baz=baz",
   379                           "QUX==qux",
   380                           "FOOBAR=foo bar",
   381                           "FOOBARBAZ='foo bar baz'",
   382                           "QUX2=\"qux\""],
   383      "inline": ["echo \"FOO is $FOO\"",
   384                 "echo \"BAR is $BAR\"",
   385                 "echo \"BAZ is $BAZ\"",
   386                 "echo \"QUX is $QUX\"",
   387                 "echo \"FOOBAR is $FOOBAR\"",
   388                 "echo \"FOOBARBAZ is $FOOBARBAZ\"",
   389                 "echo \"QUX2 is $QUX2\""]
   390    }
   391  ]
   392  ```
   393  
   394  </Tab>
   395  </Tabs>
   396  
   397  Output:
   398  
   399  ```text
   400  docker: FOO is foo
   401  docker: BAR is bar's
   402  docker: BAZ is baz=baz
   403  docker: QUX is =qux
   404  docker: FOOBAR is foo bar
   405  docker: FOOBARBAZ is 'foo bar baz'
   406  docker: QUX2 is "qux"
   407  ```