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:
- The script runs to end of the script. The exit status of the script is that of the last command executed.
- The script runs the
exit
builtin command without arguments. Again, the exit status is that of the last command executed.
- The script runs the
exit
command with an argument. The exit status is the value of the argument.
- 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
.)(*)
- 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
.)
- The script runs into a syntax error. The exit status of the shell is nonzero. (Bash seems to use
1
.)(*)
- 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
.)