Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Why does a shebang need a path?

Wrong

#!ruby

Correct

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

The operating system should have the information regarding the path for a registered command, and why does it still expect it to be given?

share|improve this question
add comment

5 Answers 5

up vote 20 down vote accepted

Probably to keep the kernel simpler. I don't think the kernel ever searches your path to find an executable. That's handled by the C library. #! processing is done in the kernel, which doesn't use the standard C library.

Also, I don't think the kernel has a notion of what your path is. $PATH is an environment variable, and only processes have an environment. The kernel doesn't. I suppose it could access the environment of the process that did the exec, but I don't think anything currently in the kernel ever accesses environment variables like that.

share|improve this answer
    
Thanks. I think I now understand. –  sawa Apr 24 '11 at 4:58
add comment

You can get PATH-searching semantics using env, so:

#!/usr/bin/env ruby  

has the semantics you would like from

#!ruby

The reason that depending on PATH is not considered good practice is that the script can make no assumptions about the content of the PATH environment variable, breaking the "sequential dependency model" of binaries where

  1. /bin contains the executables needed at boot time;
  2. /usr/bin contains the other executables used by the OS installation;
  3. /usr/local/bin contains executables installed by the system administrator that are not part of the base OS.
  4. ~/bin contains the user's own executables.

Each level should not assume the existence of binaries later in the sequence, which are more "application" but may rely on binaries earlier, which are more "fundament". And the PATH variable tends to run from applicationy to fundamental, which is the opposite direction to the natural dependency above.

To illustrate the problem, ask yourself what happens if a script in ~/bin invokes an script in /usr/local/bin that invokes Ruby? Should that script depend on the OS installed version at /usr/bin/ruby, or on the personal copy the user happens to have at ~/bin/ruby? PATH searching gives the unpredictable semantics associated with the latter (maybe ~/bin/ruby is a broken symbolic link), while baking in the path to #! gives the former.

There isn't really any other platform-independent "operating system ... information regarding the path for a registered command", so the simplest thing is to insist on the path being provided in the #!.

share|improve this answer
add comment

I believe that's so you can specify an alternate interpreter if you need or want to. For example:

#!/home/user/myrubyinterpreter

More often seen with shell scripts:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
share|improve this answer
4  
But why would that make it necessary? You can run ruby directly with ruby, but that doesn't stop you from specifying /home/user/myrubyinterpreter if you want –  Michael Mrozek Apr 24 '11 at 3:00
    
Michael's point is exactly what I what I am asking. –  sawa Apr 24 '11 at 3:31
add comment

From Classic Shell Scripting book:

Shell scripts typically start with #! /bin/sh. Use the path to a POSIX-compliant shell if your /bin/sh isn't POSIX compliant. There are also some low-level "gotchas" to watch out for:

  • You have to know the full pathname to the interpreter to be run. This can prevent cross-vendor portability, since different vendors put things in different places (e.g., /bin/awk versus /usr/bin/awk).
share|improve this answer
add comment

There are other reasons, but from a security perspective I would never want a script to make assumptions about the correct path. What if it is wrong and it runs the wrong shell or interpreter? One that has been inserted by a malicious user? Or what if it relies on a particular shell and will crash out if the wrong shell is used?

Users may mess around with their path and break stuff - don't trust the user:-) I have conducted numerous attacks which rely on the user doing the wrong thing with their path - usually getting things in the wrong order - so I can subvert a normal script call.

Yes, I know if you've written the script yourself you can quite rightly claim that you have sorted out your own path, but an interpreter can't make those decisions.

share|improve this answer
    
This concern only applies if the script is running with elevated privileges. And that's uncommon, because shebang and setxid don't play well together, and there's a lot more to worry about than $PATH.. Without elevated privileges, what if LD_PRELOAD is used? P.S. Downvoted because giving a false warning about security is detrimental to security. –  Gilles Apr 24 '11 at 15:21
    
Your point about setxid is valid, however it is a perfectly useful attack vector so definitely isn't a false warning –  Rory Alsop Apr 24 '11 at 16:16
1  
Could you give an example of a case where PATH is an attack vector, and there aren't so many other attack vectors that the whole approach should be rethought? –  Gilles Apr 25 '11 at 17:38
    
@Gilles - +1 you have a good point, definitely, as if this is broken there are probably other ways in that are just as valid, however in terms of broken things you can fix, this is an easy one. –  Rory Alsop Apr 26 '11 at 7:46
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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