Is it possible to set -e for shell provisioner globally?

Hi, everyone!
We build macOS VM images using the vsphere-clone builder and noticed odd behavior when executing shell provisioner scripts — script execution doesn’t stop even if there is some error like:
==> vsphere-clone: rm: /etc/localtime: Permission denied
The sample provision block looks like this:

{
    "type": "shell",
    "scripts": [
        "./provision/configuration/configure-machine.sh"
    ],
    "environment_vars": [
        "PASSWORD={{user `vm_password`}}",
        "USERNAME={{user `vm_username`}}"
    ]
}

And the sample script is:

# Setting correct time zone
echo "Configuring system time to GMT..."
rm -f /etc/localtime
ln -sf /usr/share/zoneinfo/UTC /etc/localtime

If we put #!/bin/sh -e at the beginning of the script then the behavior changes and the script started to fail as expected, but it’s quite painful to maintain over 100 scripts.
The question — is it possible to somehow set -e in the execute command?
I’ve tried "execute_command": "{{ .Vars }} /bin/sh -e {{ .Path }}" without any luck.
Any help is appreciated! :sweat_smile:

Hi! This is a bit tricky because by default bash scripts and subprocesses don’t inherit their parents’ settings.

I tinkered a bit and found a hack that worked for me; by setting the SHELLOPTS env var I could get the flags passed in the bash call to be respected by the script:

		{
			"type": "shell-local",
			"environment_vars": ["SHELLOPTS=asdf"],
			"execute_command": ["/bin/bash", "-cex", "{{.Vars}} {{.Script}}"],
			"scripts": ["./fail_shell.sh"]
		}

I tested this using the script “fail_shell.sh” which is pretty simple:

#!/bin/bash

# this should pass
echo "test"

# this should fail
echo pancakes | grep bananas

# this should pass
echo "test"

If you change the command

			"execute_command": ["/bin/bash", "-cex", "{{.Vars}} {{.Script}}"],

to

			"execute_command": ["/bin/bash", "-c", "{{.Vars}} {{.Script}}"],

You’ll see that the errexit and verbose execution get turned off for the script.

Hope this helps!

2 Likes

Thanks! Will give it a try tomorrow! My only concern if that works on macOS or not because default bash version came from something like 2007 and doesn’t support all of the modern features. Have you tried it on macOS or some Linux distro?

I was on macos when I tried it out :slight_smile:

1 Like

@SwampDragons one more question :sweat: Have you done the same not for shell-local, but for shell provisioner? I’ve tried several execute_command forms and didn’t get success so far.

I haven’t had a chance to tinker with that, sorry.