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