Live data from Hacker News

A surprise with how '#!' handles its program argument in practice

utcc.utoronto.ca

61–70 of 116 posts

Re: A surprise with how '#!' handles its program argument in practice

#61
The authors previous article about "...(not) using #!/usr/bin/env whatever" doesn't sit well with me.

"The only reason to start your script with '#!/usr/bin/env ' is if you expect your script to run on a system where Bash or whatever else isn't where you expect (or when it has to run on systems that have '' in different places, which is probably most common for third party packages)."

His very first point is how you should only use it don't know where to expect bash binary, when I feel like, while it's probably safe in most nix os', assuming it limits future enhancements by requiring that binary be in place. However unlikely it would need to or someone would want to move it.

Re: A surprise with how '#!' handles its program argument in practice

#62
post #39

Earlier quoted context omitted.

Wait... your interpreter reads from stdin. Shouldn't it read its first arg, instead?

I think that was what I was trying to figure out, how the program was passed. but OpenBSD does not do nested interpreters, it looks like if I had tried Linux it would have worked.

[deleted]

Re: A surprise with how '#!' handles its program argument in practice

#63
post #48
post #23

Earlier quoted context omitted.

Because /bin is the standard location for bash. The only one that breaks that expectation is NixOS (and maybe GuixSD?), apparently. I'm surprised they didn't symlink /bin or put a stub. Last time I tried NixOS was like 10 years ago. I thought there was a /bin/bash, but maybe it was just a /bin/sh? Other interpreters like python, ruby, etc. have more likelyhood of being used with "virtual environments", so it's more c…

/bin is the "standard" location for bash on a subset of Linux distributions and basically no other Unix... So it's not really a standard. /bin/sh is a much more common convention but once again, not a standard. There really isn't a truly portable shebang, but the same can be said about executables themselves. As part of the build or install step of whatever thing you're making, you should really be looking these up a…

Pretty much. I will continue using "#!/usr/bin/env ".

Re: A surprise with how '#!' handles its program argument in practice

#64

I wonder what the reason was for having the kernel handle this, instead of the shell? To allow programs besides the shell to execute interpreted scripts as if they were actual binaries? This is of course in stark contrast to dynamic linking, which is performed by a userspace program instead of the kernel, and much like the #!, this "interpreter"'s path is also hardcoded in dynamically linked binaries.

Remember how slow early machines were. An unnecessary additional 'exec' would have seemed very wasteful, especially as most of the initial uses would have been shell scripts, so you would be execing the shell twice.

Re: A surprise with how '#!' handles its program argument in practice

#65
post #29

The thing that surprised me was that you can't write an interpreter in an interpreted language, at least not in obsd. It is possible if you jump through a few hoops but you can't directly call it. An example: if you made a language in python /bin/my_lang: #does nothing but pretend it does #!/usr/local/bin/python3 import sys print('my_lang args', sys.argv) for line in sys.stdin: print('invalid_line:', line) my_script:…

Wait... your interpreter reads from stdin. Shouldn't it read its first arg, instead?

IIRC interpreters can also read their programs from stdin. Try piping a script to bash and see if it works.

(Actually, this is how the `curl install.sh | bash` anti pattern works. )

Re: A surprise with how '#!' handles its program argument in practice

#67

The authors previous article about "...(not) using #!/usr/bin/env whatever" doesn't sit well with me. "The only reason to start your script with '#!/usr/bin/env ' is if you expect your script to run on a system where Bash or whatever else isn't where you expect (or when it has to run on systems that have ' ' in different places, which is probably most common for third party packages)." His very first point is how you…

I've encountered systems that only have bash in /bin/bash, or in /usr/bin/bash, and it's a hell of a pain to have to fix every script when using different distros (I think it must've been an old Fedora and Ubuntu?).

Nowadays, most distros are moving towards having /bin be a symlink to /usr/bin, so it's mattering less and less, but I see no reason not to just do /usr/bin/env which is supposed to be on the same place on every distro.

Re: A surprise with how '#!' handles its program argument in practice

#68
post #2

Huh. I wish I had known this before. NixOS is annoying because everything is weird and symlinked and so I find myself fairly frequently making the mistake of writing `#!/bin/bash`, only to be told it can't find it, and I have to replace the path with `/run/current-system/sw/bin/bash`. Or at least I thought I did; apparently I can just have done `#!bash`. I just tested this, and it worked fine. You learn something new…

Anything other than ”#!/usr/bin/env bash” is doomed to fail at some time.

If that fails, I assume the user knows enough about their environment to fix it.

Re: A surprise with how '#!' handles its program argument in practice

#69
post #15

Earlier quoted context omitted.

You can use `#!/usr/bin/env bash` on NixOS

I didn't know that actually. I'll start using that from this point forward.

It is good practice to be using it everywhere.

Re: A surprise with how '#!' handles its program argument in practice

#70
post #39

Earlier quoted context omitted.

Wait... your interpreter reads from stdin. Shouldn't it read its first arg, instead?

I think that was what I was trying to figure out, how the program was passed. but OpenBSD does not do nested interpreters, it looks like if I had tried Linux it would have worked.

[deleted]
Post reply on HN