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 ```