2

I know that in shell-scripting an "exit" usually means voluntarily or at least successfully terminating a session (or a process within a session) and that there are several different exit modes; the following are these I know:

1. A simple exit command

If I'm in the first shell-session (shell-session 0) it will usually cause the shell CLI window to close, but if I'm in some sub-session (like shell-session 1 or later) execution will usually just move my user back to the previous session (say 1 → 0).

2. An exit SOME_EXIT-CODE command

I find three main exit codes used in such exiting:

  1. exit 0 (success).
  2. exit 1 (general error such as "divide by zero" and other impermissible operations).
  3. exit 2 (as in Bash 4.x.x - misuse of shell builtins, and an example would be an empty function; myFunc() {}).

I often find these added to the end of command sequences as indicators of their execution's outcome; sometimes as part of unit testing, as in:

domain="$1" && test -z "$domain" && exit 2 
# Test if a user passes only one domain as a parameter, when executing this script

3. A non-added script exit

If I'm not wrong, when a Bash script ends to run, its "ending" is actually an "exiting" in the common *nix terminology - the script itself is a session from which the user exits back to the CLI sesssion. Here also, some exit code, might be given.

My question

Are there any other "exit modes" in shell scripting in general, and in Bash in particular?

  • If the existing answers do not answer your question, please either edit your question to clarify or comment on the closest answer to indicate what you are still unclear about. – DopeGhoti Oct 1 '18 at 15:34
  • Are you asking about the exit status codes and their meaning, or about the different ways and reasons a script might terminate, or what is it, exactly? – ilkkachu Oct 2 '18 at 0:11
  • @ilkkachu I ask on the different ways a script could terminate (by that, even a single code line on the CLI without a file or heredocument), , but specifically what are the possible exit terminations and not any kind of termination. – JohnDoea Oct 2 '18 at 7:09
5
+100

an "exit" usually means voluntarily or at least successfully terminating

At least the POSIX text seems to use exit solely for voluntary termination of a process, as opposed to being killed for an outside reason. (See e.g. wait()) A process being killed by a signal hardly counts as a success, so any successful termination must in that sense be an "exit". Though I'd expect those terms to be used less strictly in informal use.

Are there any other "exit modes" in shell scripting in general, and in Bash in particular?

Mode has particular technical meanings in some contexts (e.g. chmod()), but I can't think of one here, so I'm not exactly sure what it is you're asking.

In any case, a shell script might exit terminate at least due to the following reasons:

  1. The script runs to end of the script. The exit status of the script is that of the last command executed.
  2. The script runs the exit builtin command without arguments. Again, the exit status is that of the last command executed.
  3. The script runs the exit command with an argument. The exit status is the value of the argument.
  4. The script references an unset variable while set -u/set -o nounset is in effect. The exit status depends on the shell, but is nonzero. (Bash seems to use 127.)(*)
  5. The script runs a command that fails while set -e/set -o errexit is in effect. The exit status is that of the failing command. (But see BashFAQ 105 for issues with set -e.)
  6. The script runs into a syntax error. The exit status of the shell is nonzero. (Bash seems to use 1.)(*)
  7. The script receives a signal that causes it to terminate. Not all signals cause termination, and signals can be either ignored or a handler can be set within the script with the trap builtin command. This also applies to e.q. hitting Ctrl-C, which sends the SIGINT signal.(*)

In the technical sense, in cases 1 to 6, the shell process running the script exits voluntarily (i.e. the process calls exit()). On the other hand, from the point of view of the script itself, terminating due to set -e, set -u or a syntax error might well be called involuntary. But the shell script is not the same as the shell interpreter.

In 1 to 3, the custom is to use an exit status of zero for a successful completion, and a non-zero value for failures. The exact meaning of the non-zero values depends on the utility. Some might use only zero and one, some might use different non-zero statuses for different situations. For example, grep uses 1 to indicate no match was found, and values greater than 1 to indicate errors. Bash's builtins also use 2 to indicate errors like invalid options. Using a similar custom may be useful, but you'll need to document what the exit status of your script means. Note that the exit status is usually limited to 8 bits, so the range is from 0 to 255.

In 4 to 6, the situation is usually considered some sort of a failure, so the exit status is non-zero. In 7, there is no exit status. Instead, when a process terminates due to a signal, the wait() system call indicates the signal in question. If the parent process is a shell, it usually represents this with an exit status of 128 + <signal number>, e.g. 143 for a child terminated with SIGTERM.

(* Unlike scripts, interactive shells will not exit due to syntax errors or set -u or SIGINT.)

If I'm in the first shell-session it will usually cause the shell CLI window to close

A terminal emulator will usually close if the process it started exits. But that's up to the terminal emulator, not a function of the shell. A terminal emulator might decide to keep the window open to tell the user that their program terminated, and you could run something other than a shell within a terminal emulator, too.

if I'm in some sub-session,execution will usually just move my user back to the previous session.

If you use an interactive shell to start another shell, the parent shell continues when the child terminates. But again, this isn't related to shells, the same happens if you start an editor or just run any command from an interactive shell. When the child process terminates, the parent shell continues accepting commands from the user.

Bash does keep a variable SHLVL that is increased by one each time Bash starts, so in a sense it does have an internal idea of nested shells. But I don't think the phrase "sub-session" is very common, let alone any sort of numbering of such. (I think SHLVL initializes at 1.)

3

There aren't really different "modes" of exiting.

Using exit with no argument will use the return code of the previous command as the return code. If this is the final command in a script, it is effectively a NOOP unless the script is being sourced.

exit 0 is explicitly setting the return code to 0, the standard exit code for a non-error state.

Using a number other than 0 is simply doing the same thing: setting the return code to the specified value.

When a script ends without an exit instruction, the exit code of the final command executed by the command is used.

If you trap '[...]' EXIT, and include an exit statement in the trap, it will supercede this as the trap will be executed (including any included exit commands) before the script actually terminates.

  • An exit with no number would exit with the result code of the most recently executed command. This may not always be zero. – Kusalananda Sep 28 '18 at 16:28
1

There are many more exit codes than just 0, 1 and 2. See:

Thinking about the exit codes, you should remember that scripts not always end where you might suspect them to. Before they're finished, They may be killed with a signal, or they may end due to an unplanned input terminator from pressing Ctrl-D, producing unexpected exits. A good understanding and analysis is thus needed with scripts, especially those that return numerous codes.

1

I am not sure if I understood the question correctly but you seem to seek the different ways a program terminates instead of exits ?

  • you can have the shell (or command ran by a shell) exit like you said (ex: Your interactive shell will exit if it encouteres EoF. Any shell will also exit if it runs out of commands to run (end of script), or if it encounters an exit (ex: "exit 2" in a shell makes it exit with returncode 2)

  • you could receive a "HUP" if the parent shell exits and no "nohup" (or variant thereof) were run to detach your process from that parent shell

  • you could receive a Ctrl-C

  • you could run out of memory/cpu/something (fd?)

  • you could receive a kill -9 or other (the script itself could "kill -9 $$" itself that way, even if it's weird...)

  • your shell could be on the right-hand-side of a pipe which breaks because the left end side end abruptly

  • and I bet there are many more cases....

Each one of those should terminate the program/shell, and each a bit differently (and you can trap some of them to do something before exiting, or prevent exiting altogether (for ctrl-C, for ex, you could trap the INT signal))

  • I didn't know we should distinct program termination from program exiting (or session termination / exitation) in shell-scripting. Is it really needed? I don't recall ever actually using the term "program termination" ever in any software context; you might want to add a pretext about this distinction at the start of the answer. – JohnDoea Oct 1 '18 at 11:41
  • @JohnDoea I meant to differentiate the ways a program can exit "normally", from the cases it is terminated from something outside of it (ctrl-C, HUP signal, kill -9, etc). those latter ones terminate the program which hasn't properly "exited" (but which still exits in the process, if it has time. kill -9 doesn't leave it any time to do so, for exemple). Exit is imo ambiguous as it can designate the "end of program / reached an 'exit' statement" but doesn't really cover the other causes of termination. To me, "termination" is wider and less linked to the "exit" keyword. – Olivier Dulac Oct 1 '18 at 11:44
  • Olivier, I edited the question to include the good distinction you made between terminating and exiting. You might want to review the change and edit the answer (not critical). – JohnDoea Oct 1 '18 at 15:43
  • @JohnDoea : thx for that but I'm sorry I don't see your edit.. (via phone official app at least). It may have been rejected by reviewers? I believe there is already some distinction but I'll think on how I may improve the answer and its wordings. And ikkachu added one with the same idea but much better in the way of formalism and standards – Olivier Dulac Oct 5 '18 at 8:54

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.