14

I am new to shell scripts and many books have written that use #!(sha-bang) line in starting of the script to invoke the interpreter .And this will invoke a new shell for script and do the interpretation line by line.But one of my basic script is still running without the magic line.

so my questions are:

  • from where did my basic script get the interpreter.
  • how did the script manages to locate the interpreter.

now let me tell you about my basic script it just contains the following line:

echo "basic script without the magic lines"

1

3 Answers 3

10

When you execute a program, the kernel checks whether it starts by some magic byte sequence. If the executable file starts with #!, the kernel interprets the rest of the line as an interpreter name. If the executable file starts with \177ELF (where \177 is byte 127), it loads the file as an ELF executable; that's the normal kind on most unix systems nowadays.

If the kernel doesn't recognize the file format, it refuses to execute the file and returns the error ENOEXEC (Exec format error). When the shell notices that, it takes upon itself to execute the program as a shell script.

To witness this in action, add a few commands to your script:

ps l $$
ls -l /proc/$$/exe
echo hello

(This is for Linux, adjust for other unices.) Then try running that script from various shells. You'll see that some shells spawn a new instances of themselves to execute the script (bash, ksh93) while others spawn /bin/sh (dash, pdksh, zsh).

6
  • What do I look for with your ls -l command? This: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash - ? If so, what does it say? Also, noticed I have SHELL=/bin/bash on env, but changing it didn't seem to change behaviour. Maybe it is unrelated? Commented Oct 11, 2012 at 3:21
  • it seems like you are changing shell variable "SHELL".if yes,then you are only chnging the value of shell variable SHELL.it wont chnge your shell.for chnaging your shell edit the /etc/passwd file. Commented Oct 11, 2012 at 5:31
  • 2
    @EmanuelBerg Yes (I should have written ls -l /proc/$$/exe, in fact). The exe links points to the shell that's executing your script. When you run your script, you'll see that it's bash that interprets the script. If you run it from e.g. pdksh, it runs /bin/sh. I don't know of any shell that uses the SHELL environment variable or the login shell in that circumstance. Commented Oct 11, 2012 at 9:37
  • 3
    @user1678213 Changing the shell in /etc/passwd changes what shell is executed when you log in over SSH or on a text console. It doesn't change which shell might execute scripts. Commented Oct 11, 2012 at 9:38
  • 2
    @user1678213 I verified what I wrote here by running tests. None of the shells I tested looked in /etc/passwd to decide which shell to use, they either forked an instance of themselves or executed /bin/sh. Commented Oct 11, 2012 at 12:22
3

If the magic line is not provided, a default shell is used to run the script. This default shell could either be Bourne shell (sh) which is the case in some flavors, however, in some other flavors, the default shell used is same as login shell to execute it. The thing is: Don't leave it to the system to decide the shell, always provide the shell which you want in the first line.

5
  • 1
    yup..may be my current shell is invoking a default shell for shell script not having magic numbers. Commented Oct 10, 2012 at 6:55
  • 1
    @user1678213 Yes, it's your shell (and not the kernel) that's doing this. Commented Oct 11, 2012 at 0:26
  • 1
    I believe POSIX mandates that /bin/sh is used in this case.
    – vonbrand
    Commented Jan 30, 2013 at 20:33
  • 2
    @vonbrand This is a common misconception. POSIX doesn't mandate the POSIX shell to be /bin/sh, just to be the first sh executable found while exploring a conforming PATH.
    – jlliagre
    Commented Jul 24, 2013 at 0:03
  • 4
    That's incorrect, it's never the "login shell" that is used to execute it. What can happen though is that the calling shell (if the script is called from a shell) may have a child of itself interpreting it. Commented Jul 24, 2013 at 2:08
-2

It's probably one of the following 3 possibilities:

  1. You are calling the script directly with the interpreter, IE: bash script.sh

  2. The name of the script file has an .sh extension, which gets the system to look for the default program for this type of file

  3. The shell environment that you are using is executing the 'echo' by itself, since I can only guess that the script file is executable. If, for example, you will be using a bash shell and have a command in your file that is used only by ksh, then you will see that it will not work.

Good luck!

3
  • 3
    neither did i call it with bash nor with any extension. Commented Oct 10, 2012 at 6:19
  • 1
    and shell environment is not executing it because when i invoke ps command after invoking my script. ps command shows two bash process.which means that there are two bash running. one is my login bash shell and the other one is bash for my basic_script Commented Oct 10, 2012 at 6:26
  • 1
    2: the kernel won't do anything like that. Zsh can do it, and bash can be twisted into doing it. 3: Yes, but it varies a bit between shells, see my answer. Commented Oct 11, 2012 at 0:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .