twpayne / chezmoi

Manage your dotfiles across multiple diverse machines, securely.
https://www.chezmoi.io/
MIT License
12.9k stars 478 forks source link

fork/exec error with templates #2680

Closed nodupe closed 1 year ago

nodupe commented 1 year ago

Describe the bug

Shebang needs to happen before the templating. I am not sure if this is an actual bug, but I'd like to point out that if I use a template file "run_once_before_test.tmpl" with this content:

{{ if eq .chezmoi.os  "linux" }}
#!/usr/bin/sh
ls
{{ end }}

I will receive a "fork/exec error".

I've realized that if I change it slightly to:

#!/usr/bin/sh
{{ if eq .chezmoi.os  "linux" }}
ls
{{ end }}

It works as intended.

To reproduce

create the file run_once_before_test.tmpl and add the content (on a linux machine):

{{ if eq .chezmoi.os  "linux" }}
#!/usr/bin/sh
ls
{{ end }}

do

chezmoi state reset
chezmoi init --apply

Expected behavior

Run the proper script (in this case ls on the directory chezmoi runs):

root@chezmoi:~# chezmoi init --apply
my_home_directory  snap

Output of command with the --verbose flag

root@chezmoi:~# chezmoi init --apply -v
diff --git a/once_test b/once_test
new file mode 100755
index 0000000000000000000000000000000000000000..d6ceb395a3b8c0c6703151a001d9a88d3c7daf96
--- /dev/null
+++ b/once_test
@@ -0,0 +1,4 @@
+
+#!/usr/bin/sh
+ls
+
chezmoi: fork/exec /tmp/300358282.once_test: exec format error

Output of chezmoi doctor

root@chezmoi:~# chezmoi doctor
RESULT    CHECK                MESSAGE
ok        version              v2.29.1, commit 5e7063ec11bb85efcf8e0c152dcd7dd674ed2d90, built at 2023-01-02T15:50:04Z, built by goreleaser
ok        latest-version       v2.29.1
ok        os-arch              linux/amd64 (Ubuntu 22.04.1 LTS (Jammy Jellyfish))
ok        uname                Linux chezmoi 5.15.0-52-generic #58-Ubuntu SMP Thu Oct 13 08:03:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
ok        go-version           go1.19.4 (gc)
ok        executable           /snap/chezmoi/587/chezmoi
ok        upgrade-method       snap-refresh
ok        config-file          no config file found
warning   source-dir           ~/.local/share/chezmoi is a git working tree (dirty)
ok        suspicious-entries   no suspicious entries
warning   working-tree         ~/.local/share/chezmoi is a git working tree (dirty)
ok        dest-dir             ~ is a directory
ok        umask                022
ok        cd-command           found /bin/bash
ok        cd-args              /bin/bash
info      diff-command         not set
ok        edit-command         found /usr/bin/vi
ok        edit-args            /usr/bin/vi
ok        git-command          found /usr/bin/git, version 2.34.1
ok        merge-command        found /usr/bin/vimdiff
ok        shell-command        found /bin/bash
ok        shell-args           /bin/bash
info      age-command          age not found in $PATH
ok        gpg-command          found /usr/bin/gpg, version 2.2.27
info      pinentry-command     not set
info      1password-command    op not found in $PATH
info      bitwarden-command    bw not found in $PATH
info      gopass-command       gopass not found in $PATH
info      keepassxc-command    keepassxc-cli not found in $PATH
info      keepassxc-db         not set
info      keeper-command       keeper not found in $PATH
info      lastpass-command     lpass not found in $PATH
info      pass-command         pass not found in $PATH
info      passhole-command     ph not found in $PATH
info      vault-command        vault not found in $PATH
info      secret-command       not set

Additional context

I've started using templating mainly to differentiate between windows or linux machines (also between distros sometimes). In case I am in windows a bat file should run, in linux a shell script would run. It made sense to me that the templating would add the shebang text on linux machines, and after the script would run. It is not not a real issue in my case, since bat will interpret # as a comment, and there will be no issue on the .bat execution. I can also have 2 different tmpl, one .sh and one .bat - so my usecase is "solved". I am opening the issue because it may be something worth documenting if not interestingly enough to fix.

twpayne commented 1 year ago

There is an error in your template.

The first line:

{{ if eq .chezmoi.os  "linux" }}
#!/usr/bin/sh

includes a newline character at the end of the line, so the #! occurs on the second line.

To fix this, instruct the template language to remove the whitespace by adding a - before the closing }}:

{{ if eq .chezmoi.os  "linux" -}}
#!/usr/bin/sh
twpayne commented 1 year ago

I've added an FAQ entry in 5568ec1e54e06b938ce8768a6497f6d5c94ec35d.

nodupe commented 1 year ago

Thank you, that solved my issue and I've learned a new trick! Neat!