I have a library - users are to create executable files, potentially with a hashbang to tell exec which executable to use. If they omit the hashbang, then I think most systems default to /bin/sh, I want to change that default.

So some files might start with:

#!/usr/bin/env foobar

other files might start with:

 #!/usr/bin/env perl


 #!/usr/bin/env ruby

And in some cases, the user will omit the hashbang altogether. In that case, I will still execute the file directly, and I want to default to using the foobar executable.

In other words, I don't know what the hashbang will be in advance, and I want the default to be foobar instead of the default being /bin/sh, if there is no hashbang present.

I think the way to do what I am doing is to create an executable that can run exec first, and if that fails with a particular error message, then run the script indirectly with the foobar executable?

Something like this:

function run {
  stdio=$("$1" 2>&1)
  if [[ stdout/stderr matches a certain error message ]]; then
    foobar $1

My question is - does anyone know what I am talking about - and does anyone know how I can default to a particular executable if no hashbang is present? Not that it's in theory less convenient to check if there is a hashbang, and more in theory more convenient just to run it?

  • Thanks, so it looks like the kernel will default to /bin/sh...I want to emulate that behavior, but instead of defaulting to /bin/sh I'd like to default to node. – Alexander Mills Nov 24 '17 at 21:08
  • 2
    @AlexP it’s not the kernel which uses /bin/sh, it’s the C library, and only for certain exec calls. – Stephen Kitt Nov 24 '17 at 21:53
  • I had to edit my comment because of typo, I meant "So what I was thinking, was using my own executable, manually checking for the hashbang, and if it's not there, run with foobar? does that make sense, or is there a better way?" – Alexander Mills Nov 24 '17 at 21:55
  • You're overthinking this massively, just always start it with foobar and you don't need to do any testing. – Lizardx Nov 24 '17 at 23:11
  • @Lizardx no, this is for a library...just like the Unix system itself, the sane default is /bin/sh, I simply want to create a different default, it's not as crazy as you think – Alexander Mills Nov 24 '17 at 23:12

You can implement this in two steps using execve: ask the C library to ask the kernel to execute the target, and if that fails, try again with foobar. This is actually how shells commonly implement execution.

There are other exec family functions which will run shebang-less scripts with /bin/sh, but execve won’t.

What exactly happens when I execute a file in my shell? has a lot more detail on this topic.

| improve this answer | |
  • thanks Stephen, do you think I should write this in C or Bash? do you think you could provide a start? I think Bash would better since it's more cross-platform. – Alexander Mills Nov 24 '17 at 21:52
  • 1
    I would write it in C... See the linked answer, there’s an excerpt from the Zsh source code which shows how to go about it. In Bash, you won’t be able to circumvent the /bin/sh default. – Stephen Kitt Nov 24 '17 at 21:56
  • So you've answered the question nicely, to be very specific, what I want to do is default the executable to foobar IFF the hashbang is missing and the file ends with a certain extension, otherwise default to /bin/bash. – Alexander Mills Nov 24 '17 at 23:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.