In this section, we will explain the concepts of sessions and process groups, which exist for the implementation of shell's job control.
For those unfamiliar with jobs, a job is a mechanism that shells like bash use to control processes running in the background. For example, you might use it as follows:
$ sleep infinity &  6176 #  is the job number $ sleep infinity &  6200 #  is the job number $ jobs # List the jobs - Running sleep infinity & + Running sleep infinity & $ fg 1 # Make job 1 the foreground job sleep infinity ^Z # Press Ctrl+z and control returns to bash + Stopped sleep infinity
A session corresponds to a login session when a user logs into the system through a terminal emulator like
ssh. All sessions have a terminal attached for controlling the session. When you want to operate processes within the session, you instruct them through the terminal to processes, including the shell, and receive the output from these processes. Normally, a virtual terminal named
pty/<n> is assigned to each session.
Let's consider a situation where three sessions exist:
- Alice's session: The login shell is
bash. Developing a Go program with
vimon it, and currently building some program with
- Bob's session 1: The login shell is
ps auxon it to list all processes in the system, and receiving the results with
- Bob's session 2: The login shell is
zsh. Running a custom calculation program called
This situation can be illustrated as follows:
Each session is assigned a unique value, called a "session ID" (or "SID"). Each session has a process called a session leader, which is typically a shell like
bash. The PID of the session leader equals the ID of the session. Information about the session can be obtained by
ps ajx. In the author's environment, it is as follows:
$ ps ajx PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND ... 19261 19262 19262 19262 pts/0 19647 Ss 1000 0:00 -bash ... 19262 19647 19647 19262 pts/0 19647 R+ 1000 0:00 ps ajx ...
In this case, we can see that there is a session (SID=19262) with
bash(19262) as the session leader, and
ps ajx (PID=19647) belongs to this session. Commands launched from
bash(19262) normally belong to this session. The
TTY field in
ps ajx, and in
ps aux used in previous sections, is the name of the terminal. In this session, a virtual terminal
pts/0 is assigned.
When the terminal associated with the session hangs up, a
SIGHUP is sent to the session leader. This happens when the terminal emulator's window is closed.
bash will terminate its managed jobs and then terminate itself in this case. For cases where it would be a problem if
bash terminated while a long-running process was executing, the following measures can be used:
nohupcommand: Launches a process with the setting to ignore
SIGHUP. Even if the session terminates and a
SIGHUPis sent afterward, the process does not terminate.
disownbuilt-in command of
bash: Removes a running job from
bash's management. As a result, even if
SIGHUPwill not be sent to the job.
Process groups are used to control multiple processes collectively. Within a session, there exist several process groups. Essentially, you can think of the jobs created by the shell as corresponding to process groups1.
To be more precise, the shell itself also has its own process group, but for the sake of simplicity, we will omit this from the current discussion.
Let's illustrate process groups with an example. Suppose a session is set up as follows:
- The login shell is
- From the above
go build <source name> &is executed.
- From the above
ps aux | lessis executed.
In this case, bash creates two process groups (jobs) corresponding to
go build <source name> & and
ps aux | less.
With process groups, signals can be thrown to all processes belonging to a certain process group. The shell uses this feature for job control. If you specify a negative value for the process ID argument of the
kill command, you can send a signal to the process group. For example, if you want to send a signal to a process group with a PGID of 100, you can do so with
Process groups within a session can be divided into two types:
- Foreground process group: Corresponds to the foreground job in the shell. Only one exists in a session and has direct access to the session's terminal.
- Background process group: Corresponds to the background job in the shell. When a background process tries to operate the terminal, it temporarily suspends execution as when it receives a
SIGSTOP, and this state continues until it becomes a foreground process group (or a foreground job) by commands such as the
The latter, the foreground process group (foreground job), is the one that can access the terminal directly. This is illustrated as follows.
Each process group is assigned a unique ID known as a PGID. This value can be confirmed by the
PGID field in
ps ajx. In my environment, it looks like this:
$ ps ajx | less PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND ... 19261 19262 19262 19262 pts/0 19653 Ss 1000 0:00 -bash ... 19262 19653 19653 19262 pts/0 19653 R+ 1000 0:00 ps ajx 19262 19654 19653 19262 pts/0 19653 S+ 1000 0:00 less ...
From the output, we can see that there is a login session led by
bash(19262), within which there is a process group with a PGID of 19653. The constituents of this group are
ps ajx(19653) and
less(19654), which is piped to it.
Lastly, let me also mention how to distinguish foreground process groups. In the output of
ps ajx, the processes belonging to the foreground process group have a
+ in their
The concepts of sessions and process groups can be challenging,
You might have heard the term "daemon" in the context of UNIX or Linux countless times. This section will discuss what daemons are and how they differ from regular processes. Simply put, daemons are resident processes. While regular processes are expected to terminate after completing a series of operations initiated by a user, daemons do not necessarily behave this way and may persist from system start to finish, depending on the case.
Daemons have the following characteristics:
- They do not require terminal I/O, so no terminal is assigned to them.
- They possess their own session to remain unaffected even if all login sessions end.
- Init acts as their parent process so that the process generating the daemon does not need to worry about the daemon's termination.
If illustrated, it would look like this:
However, even if they do not meet the above conditions, they may be referred to as daemons if they are resident processes.
You can determine whether a process is a daemon by looking at the results of
ps ajx. Let's take a look at
sshd, which operates as an ssh server.
$ ps ajx PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND ... 1 960 960 960 ? -1 Ss 0 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups ...
Indeed, the parent process is init (PPID is 1), and the session ID equals the PID.
Because daemons do not possess a terminal, the SIGHUP, which signifies a terminal hang-up, can be utilized for different purposes. By convention, it is often used as a signal for daemons to reread their configuration files.