github.com/hashicorp/packer@v1.14.3/website/content/docs/provisioners/powershell.mdx (about) 1 --- 2 description: | 3 The `powershell` Packer provisioner runs PowerShell scripts on Windows machines. 4 Learn how to use the provisioner with WinRM and SSH communicators. 5 page_title: powershell provisioner reference 6 --- 7 8 <BadgesHeader> 9 <PluginBadge type="official" /> 10 </BadgesHeader> 11 12 # `powershell` provisioner 13 14 The `powershell` Packer provisioner runs PowerShell scripts on Windows machines. 15 The provisioner is designed for machines using WinRM as the communicator, but you can also use the provisioner with the SSH communicator. Refer to the [Combining the PowerShell Provisioner with the SSH Communicator](#combining-the-powershell-provisioner-with-the-ssh-communicator) for 16 details. 17 18 `@include 'path/separator-note.mdx'` 19 20 ## Basic Example 21 22 The example below is fully functional. 23 24 <Tabs> 25 <Tab heading="HCL2"> 26 27 ```hcl 28 provisioner "powershell" { 29 inline = ["dir c:/"] 30 } 31 ``` 32 33 </Tab> 34 <Tab heading="JSON"> 35 36 ```json 37 { 38 "type": "powershell", 39 "inline": ["dir c:/"] 40 } 41 ``` 42 43 </Tab> 44 </Tabs> 45 46 ## Configuration Reference 47 48 @include 'provisioners/shell-config.mdx' 49 50 - `debug_mode` - If set, sets PowerShell's [PSDebug mode](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-psdebug?view=powershell-7) 51 in order to make script debugging easier. For instance, setting the value to 1 52 results in adding this to the execute command: 53 54 ```powershell 55 Set-PSDebug -Trace 1 56 ``` 57 58 - `elevated_execute_command` (string) - The command to use to execute the 59 elevated script. By default this is as follows: 60 61 ```powershell 62 powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }" 63 ``` 64 65 This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). 66 Therefore, you may use user variables and template functions in this field. In 67 addition, you may use two extra variables: 68 69 - `Path`: The path to the script to run 70 - `Vars`: The location of a temp file containing the list of 71 `environment_vars`, if configured. 72 73 - `env` (map of strings) - A map of key/value pairs to inject prior to the 74 execute_command. Packer injects some environmental variables by default into 75 the environment, as well, which are covered in the section below. Duplicate 76 `env` settings override `environment_vars` settings. This is not a JSON 77 template engine enabled function. HCL interpolation works as usual. 78 79 - `environment_vars` (array of strings) - An array of key/value pairs to 80 inject prior to the execute_command. The format should be `key=value`. 81 Packer injects some environmental variables by default into the 82 environment, as well, which are covered in the section below. 83 84 - `use_pwsh` (boolean) - Run `pwsh.exe` instead of `powershell.exe`. Defaults to false. 85 86 This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you 87 may use user variables and template functions in this field. If you are 88 running on AWS, Azure, Google Compute, or OpenStack and would like to access 89 the autogenerated password that Packer uses to connect to the instance via 90 WinRM, you can use the `build` template engine to inject it using 91 `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by 92 accessing the `build` variables For example: 93 94 <Tabs> 95 <Tab heading="HCL2"> 96 97 ```hcl 98 provisioner "powershell" { 99 environment_vars = ["WINRMPASS=${build.Password}"] 100 inline = ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""] 101 } 102 ``` 103 104 </Tab> 105 <Tab heading="JSON"> 106 107 ```json 108 { 109 "type": "powershell", 110 "environment_vars": ["WINRMPASS={{ build `Password` }}"], 111 "inline": ["Write-Host \"Automatically generated aws password is: $Env:WINRMPASS\""] 112 }, 113 ``` 114 115 </Tab> 116 </Tabs> 117 118 - `execute_command` (string) - The command to use to execute the script. By 119 default this is as follows: 120 121 ```powershell 122 powershell -executionpolicy bypass "& { if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit $LastExitCode }" 123 ``` 124 125 This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). 126 Therefore, you may use user variables and template functions in this field. In 127 addition, you may use two extra variables: 128 129 - `Path`: The path to the script to run 130 - `Vars`: The location of a temp file containing the list of 131 `environment_vars`, if configured. 132 The value of both `Path` and `Vars` can be manually configured by setting 133 the values for `remote_path` and `remote_env_var_path` respectively. 134 135 If you use the SSH communicator and have changed your default shell, you 136 may need to modify your `execute_command` to make sure that the command is 137 valid and properly escaped; the default assumes that you have not changed 138 the default shell away from cmd. 139 140 - `elevated_user` and `elevated_password` (string) - If specified, the 141 PowerShell script will be run with elevated privileges using the given 142 Windows user. 143 144 This is a [template engine](/packer/docs/templates/legacy_json_templates/engine). Therefore, you 145 may use user variables and template functions in this field. If you are 146 running on AWS, Azure, Google Compute, or OpenStack and would like to access 147 the autogenerated password that Packer uses to connect to the instance via 148 WinRM, you can use the `build` template engine to inject it using 149 `` {{ build `Password` }} ``. In HCL templates, you can do the same thing by 150 accessing the `build` variables For example: 151 152 <Tabs> 153 <Tab heading="HCL2"> 154 155 ```hcl 156 provisioner "powershell" { 157 elevated_user = "Administrator" 158 elevated_password = build.Password 159 } 160 ``` 161 162 </Tab> 163 <Tab heading="JSON"> 164 165 ```json 166 { 167 "type": "powershell", 168 "elevated_user": "Administrator", 169 "elevated_password": "{{ build `Password` }}", 170 ... 171 }, 172 ``` 173 174 </Tab> 175 </Tabs> 176 177 If you specify an empty `elevated_password` value then the PowerShell 178 script is run as a service account. For example: 179 180 <Tabs> 181 <Tab heading="HCL2"> 182 183 ```hcl 184 provisioner "powershell" { 185 elevated_user = "SYSTEM" 186 elevated_password = "" 187 } 188 ``` 189 190 </Tab> 191 <Tab heading="JSON"> 192 193 ```json 194 { 195 "type": "powershell", 196 "elevated_user": "SYSTEM", 197 "elevated_password": "", 198 ... 199 }, 200 ``` 201 202 </Tab> 203 </Tabs> 204 205 - `execution_policy` - To run ps scripts on Windows, Packer defaults this to 206 "bypass" and wraps the command to run. Setting this to "none" will prevent 207 wrapping, allowing to see exit codes on Docker for Windows. Possible values 208 are `bypass`, `allsigned`, `default`, `remotesigned`, `restricted`, 209 `undefined`, `unrestricted`, and `none`. 210 211 - `remote_path` (string) - The path where the PowerShell script will be 212 uploaded to within the target build machine. This defaults to 213 `C:/Windows/Temp/script-UUID.ps1` where UUID is replaced with a dynamically 214 generated string that uniquely identifies the script. 215 216 This setting allows users to override the default upload location. The 217 value must be a writable location and any parent directories must already 218 exist. 219 220 - `remote_env_var_path` (string) - Environment variables required within the 221 remote environment are uploaded within a PowerShell script and then enabled 222 by 'dot sourcing' the script immediately prior to execution of the main 223 command or script. 224 225 The path the environment variables script will be uploaded to defaults to 226 `C:/Windows/Temp/packer-ps-env-vars-UUID.ps1` where UUID is replaced with a 227 dynamically generated string that uniquely identifies the script. 228 229 This setting allows users to override the location the environment variable 230 script is uploaded to. The value must be a writable location and any parent 231 directories must already exist. 232 233 - `skip_clean` (bool) - Whether to clean scripts up after executing the provisioner. 234 Defaults to false. When true any script created by a non-elevated Powershell 235 provisioner will be removed from the remote machine. Elevated scripts, 236 along with the scheduled tasks, will always be removed regardless of the 237 value set for `skip_clean`. 238 239 - `start_retry_timeout` (string) - The amount of time to attempt to _start_ 240 the remote process. By default this is `5m` or 5 minutes. This setting 241 exists in order to deal with times when SSH may restart, such as a system 242 reboot. Set this to a higher value if reboots take a longer amount of time. 243 244 - `pause_after` (string) - Wait the amount of time after provisioning a PowerShell 245 script, this pause be taken if all previous steps were successful. 246 247 @include 'provisioners/common-config.mdx' 248 249 ## Default Environmental Variables 250 251 In addition to being able to specify custom environmental variables using the 252 `environment_vars` configuration, the provisioner automatically defines certain 253 commonly useful environmental variables: 254 255 - `PACKER_BUILD_NAME` is set to the [name of the 256 build](/packer/docs/templates/legacy_json_templates/builders#named-builds) that Packer is running. 257 This is most useful when Packer is making multiple builds and you want to 258 distinguish them slightly from a common provisioning script. 259 260 - `PACKER_BUILDER_TYPE` is the type of the builder that was used to create 261 the machine that the script is running on. This is useful if you want to 262 run only certain parts of the script on systems built with certain 263 builders. 264 265 - `PACKER_HTTP_ADDR` If using a builder that provides an HTTP server for file 266 transfer (such as `hyperv`, `parallels`, `qemu`, `virtualbox`, and `vmware`), this 267 will be set to the address. You can use this address in your provisioner to 268 download large files over HTTP. This may be useful if you're experiencing 269 slower speeds using the default file provisioner. A file provisioner using 270 the `winrm` communicator may experience these types of difficulties. 271 272 ## Combining the PowerShell Provisioner with the SSH Communicator 273 274 The good news first. If you are using the [Microsoft port of 275 OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/wiki) then the provisioner 276 should just work as expected - no extra configuration effort is required. 277 278 Now the caveats. If you are using an alternative configuration, and your SSH 279 connection lands you in a \*nix shell on the remote host, then you will most 280 likely need to manually set the `execute_command`; The default 281 `execute_command` used by Packer will not work for you. When configuring the 282 command you will need to ensure that any dollar signs or other characters that 283 may be incorrectly interpreted by the remote shell are escaped accordingly. 284 285 The following example shows how the standard `execute_command` can be 286 reconfigured to work on a remote system with 287 [Cygwin/OpenSSH](https://cygwin.com/) installed. The `execute_command` has each 288 dollar sign backslash escaped so that it is not interpreted by the remote Bash 289 shell - Bash being the default shell for Cygwin environments. 290 291 <Tabs> 292 <Tab heading="HCL2"> 293 294 ```hcl 295 provisioner "powershell" { 296 execute_command = "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\"" 297 inline = [ "Write-Host \"Hello from PowerShell\""] 298 } 299 ``` 300 301 </Tab> 302 <Tab heading="JSON"> 303 304 ```json 305 "provisioners": [ 306 { 307 "type": "powershell", 308 "execute_command": "powershell -executionpolicy bypass \"& { if (Test-Path variable:global:ProgressPreference){\\$ProgressPreference='SilentlyContinue'};. {{.Vars}}; &'{{.Path}}'; exit \\$LastExitCode }\"", 309 "inline": ["Write-Host \"Hello from PowerShell\""] 310 } 311 ] 312 ``` 313 314 </Tab> 315 </Tabs> 316 317 ## Packer's Handling of Characters Special to PowerShell 318 319 The escape character in PowerShell is the `backtick`, also sometimes referred 320 to as the `grave accent`. When, and when not, to escape characters special to 321 PowerShell is probably best demonstrated with a series of examples. 322 323 ### When To Escape... 324 325 Users need to deal with escaping characters special to PowerShell when they 326 appear _directly_ in commands used in the `inline` PowerShell provisioner and 327 when they appear _directly_ in the users own scripts. Note that where double 328 quotes appear within double quotes, the addition of a backslash escape is 329 required for the JSON template to be parsed correctly. 330 331 <Tabs> 332 <Tab heading="HCL2"> 333 334 ```hcl 335 provisioner "powershell" { 336 inline = [ 337 "Write-Host \"A literal dollar `$ must be escaped\"", 338 "Write-Host \"A literal backtick `` must be escaped\"", 339 "Write-Host \"Here `\"double quotes`\" must be escaped\"", 340 "Write-Host \"Here `'single quotes`' don`'t really need to be\"", 341 "Write-Host \"escaped... but it doesn`'t hurt to do so.\"", 342 ] 343 } 344 ``` 345 346 </Tab> 347 <Tab heading="JSON"> 348 349 ```json 350 "provisioners": [ 351 { 352 "type": "powershell", 353 "inline": [ 354 "Write-Host \"A literal dollar `$ must be escaped\"", 355 "Write-Host \"A literal backtick `` must be escaped\"", 356 "Write-Host \"Here `\"double quotes`\" must be escaped\"", 357 "Write-Host \"Here `'single quotes`' don`'t really need to be\"", 358 "Write-Host \"escaped... but it doesn`'t hurt to do so.\"" 359 ] 360 } 361 ] 362 ``` 363 364 </Tab> 365 </Tabs> 366 367 The above snippet should result in the following output on the Packer console: 368 369 ```shell-session 370 ==> amazon-ebs: Provisioning with Powershell... 371 ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner508190439 372 amazon-ebs: A literal dollar $ must be escaped 373 amazon-ebs: A literal backtick ` must be escaped 374 amazon-ebs: Here "double quotes" must be escaped 375 amazon-ebs: Here 'single quotes' don't really need to be 376 amazon-ebs: escaped... but it doesn't hurt to do so. 377 ``` 378 379 ### When Not To Escape... 380 381 Special characters appearing in user environment variable values and in the 382 `elevated_user` and `elevated_password` fields will be automatically dealt with 383 for the user. There is no need to use escapes in these instances. 384 385 <Tabs> 386 <Tab heading="HCL2"> 387 388 ```hcl 389 variable "psvar" { 390 type = string 391 default = "My$tring" 392 } 393 394 build { 395 sources = ["source.amazon-ebs.example"] 396 397 provisioner "powershell" { 398 elevated_user = "Administrator" 399 elevated_password = "Super$3cr3t!" 400 inline = ["Write-Output \"The dollar in the elevated_password is interpreted correctly\""] 401 } 402 provisioner "powershell" { 403 environment_vars = [ 404 "VAR1=A$Dollar", 405 "VAR2=A`Backtick", 406 "VAR3=A'SingleQuote", 407 "VAR4=A\"DoubleQuote", 408 "VAR5=${var.psvar}", 409 ] 410 inline = [ 411 "Write-Output \"In the following examples the special character is interpreted correctly:\"", 412 "Write-Output \"The dollar in VAR1: $Env:VAR1\"", 413 "Write-Output \"The backtick in VAR2: $Env:VAR2\"", 414 "Write-Output \"The single quote in VAR3: $Env:VAR3\"", 415 "Write-Output \"The double quote in VAR4: $Env:VAR4\"", 416 "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\"", 417 ] 418 } 419 } 420 ``` 421 422 </Tab> 423 <Tab heading="JSON"> 424 425 ```json 426 { 427 "variables": { 428 "psvar": "My$tring" 429 }, 430 ... 431 "provisioners": [ 432 { 433 "type": "powershell", 434 "elevated_user": "Administrator", 435 "elevated_password": "Super$3cr3t!", 436 "inline": "Write-Output \"The dollar in the elevated_password is interpreted correctly\"" 437 }, 438 { 439 "type": "powershell", 440 "environment_vars": [ 441 "VAR1=A$Dollar", 442 "VAR2=A`Backtick", 443 "VAR3=A'SingleQuote", 444 "VAR4=A\"DoubleQuote", 445 "VAR5={{user `psvar`}}" 446 ], 447 "inline": [ 448 "Write-Output \"In the following examples the special character is interpreted correctly:\"", 449 "Write-Output \"The dollar in VAR1: $Env:VAR1\"", 450 "Write-Output \"The backtick in VAR2: $Env:VAR2\"", 451 "Write-Output \"The single quote in VAR3: $Env:VAR3\"", 452 "Write-Output \"The double quote in VAR4: $Env:VAR4\"", 453 "Write-Output \"The dollar in VAR5 (expanded from a user var): $Env:VAR5\"" 454 ] 455 } 456 ] 457 ... 458 } 459 ``` 460 461 </Tab> 462 </Tabs> 463 464 The above snippet should result in the following output on the Packer console: 465 466 ```shell-session 467 ==> amazon-ebs: Provisioning with Powershell... 468 ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner961728919 469 amazon-ebs: The dollar in the elevated_password is interpreted correctly 470 ==> amazon-ebs: Provisioning with Powershell... 471 ==> amazon-ebs: Provisioning with PowerShell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner142826554 472 amazon-ebs: In the following examples the special character is interpreted correctly: 473 amazon-ebs: The dollar in VAR1: A$Dollar 474 amazon-ebs: The backtick in VAR2: A`Backtick 475 amazon-ebs: The single quote in VAR3: A'SingleQuote 476 amazon-ebs: The double quote in VAR4: A"DoubleQuote 477 amazon-ebs: The dollar in VAR5 (expanded from a user var): My$tring 478 ```