3

I always declare the shebang line #!/bin/bash in my shell script. Recently, when I called a script that contains an exit call, it killed my terminal. It usually kills the forked process and returned to my terminal prompt. Why might have happened that stopped the forking?

EDIT

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
  • I usually invoke script using . script_path or via a symlink to the script.
1
  • 1
    How did you invoke it? What version of bash is it?
    – Keith
    Commented Mar 14, 2011 at 2:29

3 Answers 3

5

The shebang never causes a process to fork.  It doesn't do anything UNLESS the script is executable and it is invoked in such a away that it causes the system to evaluate the shebang to see what program/shell to execute the script with.

If, for instance, you were already running in bash, and you executed the script with the source command, then the script would be executed inside the shell you were currently running, and the exit would affect that shell process, rather than it being a new shell process which got ended.

If you have a script file that you want to run, you should make it executable with the following command:

chmod +x script

Then, if you want to run the script, and if we assume that the script file is in the current directory, you use the following command:

./script

Note that this is very different from . script, which is just shorthand notation for source script.

The ./script is a relative pathname to the script file, which means search in the current directory to find the script file 'script' and then execute it — which works only if the script file is executable.

If you have script file that is NOT executable, then you can invoke it with:

bash script

But in this case you are specifying which shell to run and the shebang line is ignored.

2
  • Thank you for your reply. I run it by ". script". The strange thing happens intermittently. As I said, this didn't happen before.
    – Martin
    Commented Mar 14, 2011 at 3:04
  • 1
    The . is shorthand for the source command. If you want it to fork, you need to make the script executable, and then put it in your path somewhere, then you can execute it by typing the name, or if it is not in the path, by typing a pathname to the script. Commented Mar 14, 2011 at 3:16
6

Since sourcing a script using . causes it to run in the current shell, an exit causes the current shell to exit. You can use return to return from a sourced script as well as from a function. You cannot return from a script that was run directly.

In order to work within these constraints, you can put a conditional test in your script to do the right thing depending on whether it's sourced or run directly.

As the first line after the shebang:

called=$_

At the point you want to exit or return:

[[ $called != $0 ]] && exit || return
4
  • Clever trick. Very useful for scripts that must be sourced to work properly, like python virtualenv activate scripts.
    – hobs
    Commented Jul 12, 2012 at 16:24
  • @hobs: I include the following line as the first line instead of a shebang in any scripts that must be sourced: [[ $_ != $0 ]] || { echo "This file must be sourced to have any effect."; exit 1; } Commented Jul 12, 2012 at 18:22
  • I believe that this is backwards — it should be [[ "$called" = "$0" ]] && exit || return. (P.S. You should always quote all shell variable references unless you have a good reason not to, and you’re sure you know what you’re doing.) Another approach that is (arguably) more intuitive (requiring less head-scratching) is return 2> /dev/null || exit. Commented Jun 26, 2017 at 20:02
  • @G-Man I believe you're wrong. As far.as quoting goes, it's unnecessary inside [[ ]] since word splitting etc don't occur there. Commented Jun 26, 2017 at 22:21
4

The shebang does not cause a program to fork; whether or not the process forks is dependent on how the script is executed. Sourcing the script will cause it to run in the current interpreter, and using exec will replace the current process entirely.

You must log in to answer this question.

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