How do OS X terminal sessions persist through reboots?

Being an avid Linux user prior to buying a MacBook Pro, I typically have several terminal tabs open at any one time.

In the past, crashes and reboots would generally trash my workflow, and the majority of my respective tab histories. I searched for ways to solve this problem but always came up empty; aside from various techniques that utilised combinations of tools like ssh, screen, tmux, and required a virtual private server (or similar).

One of my favourite things about using my MacBook Pro for writing scripts, and using CLI tools, etc; is that my terminal sessions persist beyond crashes and reboots by default. In fact, I just restored a backup from almost 2 years ago, and when I logged in for the first time, I was presented with my old desktop and three bash shells that comprised a project that I was working on all that time ago.

I would like to know how OS X makes this feature possible. Does anybody here have insight into how it works?


Solution 1:

The code to restore Terminal (actually bash sessions) is part of /etc/bashrc_Apple_Terminal which gets sourced through /etc/profile and /etc/bashrc for each bash session running in Terminal.

# Resume Support: Save/Restore Shell State
#
# Terminal assigns each terminal session a unique identifier and
# communicates it via the TERM_SESSION_ID environment variable so that
# programs running in a terminal can save/restore application-specific
# state when quitting and restarting Terminal with Resume enabled.
#
# The following code defines a shell save/restore mechanism. Users can
# add custom state by defining a shell_session_save_user_state function
# that writes restoration commands to the session file at exit. e.g.,
# to save a variable:
#
#   shell_session_save_user_state() { echo MY_VAR="'$MY_VAR'" >> "$SHELL_SESSION_FILE"; }
#
# During shell startup the session file is executed. Old files are
# periodically deleted.
#
# The default behavior arranges to save and restore the bash command
# history independently for each restored terminal session. It also
# merges commands into the global history for new sessions. Because
# of this it is recommended that you set HISTSIZE and HISTFILESIZE to
# larger values.
#
# You may disable this behavior and share a single history by setting
# SHELL_SESSION_HISTORY to 0. There are some common user customizations
# that arrange to share new commands among running shells by
# manipulating the history at each prompt, and they typically include
# 'shopt -s histappend'; therefore, if the histappend shell option is
# enabled, per-session history is disabled by default. You may
# explicitly enable it by setting SHELL_SESSION_HISTORY to 1.
#
# The implementation of per-session command histories in combination
# with a shared global command history is incompatible with the
# HISTTIMEFORMAT variable--the timestamps are applied inconsistently
# to different parts of the history; therefore, if HISTTIMEFORMAT is
# defined, per-session history is disabled by default.
#
# Note that this uses PROMPT_COMMAND to enable per-session history
# the first time for each new session. If you customize PROMPT_COMMAND
# be sure to include the previous value. e.g.,
#
#   PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND; }your_code_here"
#
# Otherwise, the per-session history won't take effect until the first
# restore.
#
# The save/restore mechanism is disabled if the following file exists:
#
#   ~/.bash_sessions_disable

Solution 2:

As far as I can tell, it just saves the text in each window's scrollback buffer. It doesn't actually save the state of what was running in the terminals; it just starts a new shell after the reboot.

As an experiment, define a variable in your shell, and check its value:

foo=bar
echo $foo

Then reboot, and check the variable's value again. You'll see that it's no longer defined.