7 ms·
Seems like it only works in zsh, not bash or fish
by miffe 10mo ago
Seems like it only works in zsh, not bash or fish
- adastra22 10mo agoThe kernel interprets the shebang line, not the shell.
- jolmg 10mo agoIt is possible for the shell to handle it. From zshall(1): > If the program is a file beginning with ‘#!', the remainder of the first line specifies an interpreter for the program. The shell will execute the specified interpreter on operating systems that do not handle this executable format in the kernel. Taking a quick look at the source in Src/exec.c: execve(pth, argv, newenvp); // [...] if ((eno = errno) == ENOEXEC || eno == ENOENT) { // [...] if (ct >= 2 && execvebuf[0] == '#' && execvebuf[1] == '!') { // [...] (pprog = pathprog(ptr2, NULL))) { I guess at some point someone added that `|| eno == ENOENT` and the docs weren't updated.
- opello 10mo agoI did a little digging and found that the `|| eno == ENOENT` was added quite a bit earlier[1] than the actual pathprog lookup[2]. While I could find the "issue discussion" for the pathprog change[3] I wasn't able to find it for the ENOENT addition, which was kind of interesting and frustrating--[4] is the `X-Seq` mentioned in the commit but that seems to be inconsistent or incorrect for the actual cross-reference, and nearby in time wasn't helpful either. [1] https://sourceforge.net/p/zsh/code/ci/29ed6c7e3ab32da20f528aeba4bb76635f1a3b06/ https://sourceforge.net/p/zsh/code/ci/29ed6c7e3ab32da20f528a... [2] https://sourceforge.net/p/zsh/code/ci/29ed6c7e3ab32da20f528aeba4bb76635f1a3b06/ https://sourceforge.net/p/zsh/code/ci/29ed6c7e3ab32da20f528a... [3] https://www.zsh.org/mla/workers/2010/msg00522.html https://www.zsh.org/mla/workers/2010/msg00522.html [4] https://www.zsh.org/mla/workers/2000/msg01168.html https://www.zsh.org/mla/workers/2000/msg01168.html
- tombert 10mo agoI'm not sure the reason then, but they're definitely right; it works fine with zsh, doesn't work with bash. I wrote a test script to try it myself. I don't have fish installed and can't be bothered to go that far, but I suspect they're right about that as well.
- anotherhue 10mo agoenv bash is all well and good for normies, but if you're already on NixOS did you know you can have nix-shell be your interpreter and back flip into any reproducible interpreted environment you like? https://nixos.wiki/wiki/Nix-shell_shebang https://nixos.wiki/wiki/Nix-shell_shebang
- SAI_Peregrinus 10mo agoOr any other system with Nix installed. I use this at work to provide scripts with all their dependencies specified that work across any Linux distro & MacOS. First execution is slow since it has to fetch everything, but after that it's fast and just works.
- opello 10mo agoIt is strange, cursory digging for an explanation was a little more complex than I bargained for... https://github.com/torvalds/linux/blob/v6.17/fs/binfmt_script.c#L121-L134 https://github.com/torvalds/linux/blob/v6.17/fs/binfmt_scrip... I think it makes it to calling open_exec but there's a test for BINPRM_FLAGS_PATH_INACCESSIBLE, which doesn't seem relevant since 'bash' isn't like '/dev/fd/<fd>/..', but does provoke an ENOENT. https://github.com/torvalds/linux/blob/v6.17/fs/exec.c#L1445 https://github.com/torvalds/linux/blob/v6.17/fs/exec.c#L1445 Maybe someone else can explain it, I'd enjoy the details, and ran out of steam.
- tombert 10mo ago[tombert@puter:~/testscript]$ ./myscript.sh bash: ./myscript.sh: bash: bad interpreter: No such file or directory You are right. Appears to only work with zsh. I will resume being annoyed then.
- adastra22 10mo agoIs this UNIX?
- tombert 10mo agoThis is NixOS, so no, it's Linux. I guess I just hoped it would work on Linux as well.
- adastra22 10mo agoLinux is UNIX in the context of my question. On Linux the shebang is actually handled by the kernel. When you load a binary and attempt to execute it with a syscall, the kernel reads the first few bytes of the binary. If it is an ELF header, it executes the machine code as you would expect. If the first two bytes are "#!", then it interprets it as a shebang header and loads the specified binary to interpret it. Again, this is kernel code. I admit I'm a bit confused as to why it didn't work on your system. This shouldn't be handled at the shell level.