diff --git a/CHANGELOG.md b/CHANGELOG.md index 7218653b1..9e8a6f269 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ IMPROVEMENTS: * core: If SCP is not available, a more descriptive error message is shown telling the user. [GH-127] +* shell: Scripts are now executed by default according to their shebang, + not with `/bin/sh`. [GH-105] +* shell: You can specify what interpreter you want inline scripts to + run with `inline_shebang`. * virtualbox: Delete the packer-made SSH port forwarding prior to exporting the VM. diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index ee3b2b178..f027c5944 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -25,6 +25,9 @@ type config struct { // in the context of a single shell. Inline []string + // The shebang value used when running inline scripts. + InlineShebang string `mapstructure:"inline_shebang"` + // The local path of the shell script to upload and execute. Script string @@ -69,6 +72,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { p.config.Inline = nil } + if p.config.InlineShebang == "" { + p.config.InlineShebang = "/bin/sh" + } + if p.config.RemotePath == "" { p.config.RemotePath = DefaultRemotePath } @@ -136,6 +143,7 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { // Write our contents to it writer := bufio.NewWriter(tf) + writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang)) for _, command := range p.config.Inline { if _, err := writer.WriteString(command + "\n"); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) diff --git a/provisioner/shell/provisioner_test.go b/provisioner/shell/provisioner_test.go index 2256d313d..32d3084a5 100644 --- a/provisioner/shell/provisioner_test.go +++ b/provisioner/shell/provisioner_test.go @@ -35,6 +35,33 @@ func TestProvisionerPrepare_Defaults(t *testing.T) { } } +func TestProvisionerPrepare_InlineShebang(t *testing.T) { + config := testConfig() + + delete(config, "inline_shebang") + p := new(Provisioner) + err := p.Prepare(config) + if err != nil { + t.Fatalf("should not have error: %s", err) + } + + if p.config.InlineShebang != "/bin/sh" { + t.Fatalf("bad value: %s", p.config.InlineShebang) + } + + // Test with a good one + config["inline_shebang"] = "foo" + p = new(Provisioner) + err = p.Prepare(config) + if err != nil { + t.Fatalf("should not have error: %s", err) + } + + if p.config.InlineShebang != "foo" { + t.Fatalf("bad value: %s", p.config.InlineShebang) + } +} + func TestProvisionerPrepare_Script(t *testing.T) { config := testConfig() delete(config, "inline")