1. Introduction
In the Linux/Unix world, processes are central to our interactions with the system. Whether running a simple command or deploying a complex application, we’re interacting with processes. Effectively managing and controlling these processes is an essential skill for every developer and system administrator. You might often use Ctrl+C
to stop a runaway script or to &
toss a task into the background. But what exactly happens behind the scenes? The signal mechanism lies at the heart of it all. This article will take you deep into the Linux/Unix signal mechanism, explaining how Ctrl+C
, Ctrl+Z
, kill
, pkill
and work, analyzing nohup
and , &
how to keep processes running continuously in the background, and explaining tmux
how to interact with them. Understanding this will help you more confidently manage your system.
2. Signals: Asynchronous communication between processes
What is a signal?
Think of a signal as an “interrupt” or “notification” sent by the operating system or another process to a target process. It’s an asynchronous communication method that tells a process, “Hey, something happened, and you might want to take care of it!” These events might be a user pressing a key, a hardware error, or another process requesting an action (like exiting).
2.2. Common signals and their meanings
Linux defines many signals, each of which has a number and a name (for example SIGINT
). It is important to understand some common signals:
SIGINT
(Signal number 2): Interrupt . This is the most familiar signal, usuallyCtrl+C
triggered by the keyboard. It requests the process to interrupt the current operation.SIGQUIT
(Signal number 3): Quit signal . UsuallyCtrl+\
triggered by .SIGINT
Similar to , but also commonly used to instruct a process to exit and perform a core dump, which is convenient for debugging.SIGTSTP
(Signal number 20): Terminal Stop signal . UsuallyCtrl+Z
triggered by . It requests the process to suspend execution (suspend), and the process state will change toStopped
.SIGTERM
(Signal number 15): Terminate . This iskill
the default signal for commands without arguments. It is a polite request for the process to clean up after itself and exit. Programs can catch this signal and perform custom cleanup logic.SIGKILL
(Signal number 9): Kill signal . This is a “brutal” signal, executed directly by the kernel, used to forcibly terminate a process. A process cannot catch or ignore this signal, so it always kills the target process, but the process does not have a chance to clean up. This is a last resort.SIGHUP
(Signal number 1): Hangup . Originally used to indicate that a modem connection had been disconnected, it is now typically sent to processes (including background processes) in the session associated with the controlling terminal when that terminal is closed. Many daemons use this signal to reload their configuration files.SIGCONT
(Signal number 18): Continue signal . Used to resume a process that was suspended bySIGTSTP
or . It is used within the and commands.SIGSTOP
fg
bg
2.3. Three ways a process responds to signals
When a process receives a signal (except for some special signals), it has three options:
- Perform the default action: Each signal has a system-defined default behavior. Common default behaviors include: terminate the process, ignore the signal, terminate with core dump, suspend the process, and resume the process. For example, the default behavior
SIGINT
for andSIGTERM
is to terminate the process. - Ignore the signal: The process can explicitly tell the kernel: “I don’t care about this signal, just treat it as if it didn’t happen.”
- To capture the signal: A process can register a specific function (called a signal handler). When the signal is received, the kernel will suspend the current execution flow of the process and execute the signal handler function instead. After the execution is completed, the kernel will decide whether to resume the original execution flow based on the situation.
2.4. Special Signals: SIGKILL and SIGSTOP
Special emphasis should be placed on SIGKILL
(9) and SIGSTOP
(19), which are similar SIGTSTP
but cannot be caught. These two signals are “privileged” signals; they cannot be caught, ignored, or blocked by a process. The kernel directly performs the corresponding action (forcefully terminate or forcefully suspend) on the target process. This ensures that the system administrator always has a way to control any uncontrolled process (except for the rare cases where the process is in a special kernel state).
3. Interactive Process Control: Keyboard Shortcuts
The most commonly used process control method in the terminal is keyboard shortcuts.
3.1. Ctrl+C: Send SIGINT
- How it works: When you press in the terminal
Ctrl+C
, the terminal device driver captures this key combination and sends a signal to all processes in the foreground process groupSIGINT
. - Default behavior: The default behavior of most interactive programs (such as scripts and command-line tools) is to terminate execution after receiving
SIGINT
. - Application scenario: This is the most common way to stop the current command or program, such as stopping a long-running
ping
command or a stuck script.

3.2. Ctrl+Z: Send SIGTSTP
- How it works: Similarly,
Ctrl+Z
when you press , the terminal driver sendsSIGTSTP
a signal to the foreground process group. - Default behavior: The process that receives
SIGTSTP
suspends its execution (is suspended) and put into the background. The shell displays[1]+ Stopped my_command
a message similar to . - Application scenario: This is useful when you want to temporarily pause a foreground task (such as a compilation process) to execute another command and then return to the task. You can use
jobs
to view the suspended task, usebg %job_id
to resume it in the background, or use tofg %job_id
bring it back to the foreground to resume it.

4. Command line process control: kill and pkill
When a process runs in the background, or you want more precise control over the process, you need command-line tools.
4.1. kill Command
- grammar:
kill [-s signal | -signal] <PID> ...
- Function:
kill
The core function of this command is to send a signal to the specified process ID (PID). You need to find the PID of the target process using commands such asps
, ,pgrep
or .top
- Default signal: If no signal is specified, the
kill <PID>
defaultSIGTERM
signal (15) is sent to request the process to exit gracefully. - Common signals:
kill -9 <PID>
Orkill -SIGKILL <PID>
: SendSIGKILL
(9) signal to force the process to terminate. This is a common method for dealing with zombie processes or unresponsiveSIGTERM
processes.kill -1 <PID>
Orkill -SIGHUP <PID>
: SendSIGHUP
(1) signal, often used to notify the daemon to reload the configuration.kill -CONT <PID>
Orkill -18 <PID>
: SendSIGCONT
(18) signal to resume theSIGTSTP
suspendedSIGSTOP
process.
- Application scenario: accurately send a specific signal to a process with a known PID to implement operations such as graceful stop, forced stop, reload configuration, and resume operation.
4.2. pkill Command
- grammar:
pkill [options] <pattern>
- Function:
pkill
Going a step further, it allows you to match processes based on process name or other attributes (such as username-u user
, full command line-f
) and send signals to all matching processes. - Default signal: Again, the default is sent
SIGTERM
(15). - The difference from
kill
:kill
operates based on exact PID, whilepkill
searches for processes based on pattern matching. - Application scenarios: This is very convenient when you are unsure of the PID or want to batch process processes with the same name. For example,
pkill firefox
` will attempt to terminate allfirefox
processes named ` `.pkill -9 -f my_buggy_script.py
` will forcibly kill allmy_buggy_script.py
processes whose command lines contain ` `. Be extremely careful when usingpkill
` ` to ensure that your pattern does not accidentally damage other important processes.
5. Background execution and continuous operation: & and nohup
Sometimes we need to run a time-consuming task but don’t want it to block the current terminal.
5.1. & Operator: Putting a Process into Background Execution
- How it works: Adding “/” to the end of a command
&
, for examplemy_long_task &
, causes the shell to start the command but not wait for it to complete. Instead, it returns to the command prompt immediately, allowing you to continue entering other commands. The process runs in the background. The shell prints the job ID and PID of the background task. - Problem: Background processes started in this way remain associated with the current terminal session. When you close the terminal (exit the shell), the system typically sends
SIGHUP
a signal to all processes in that terminal session, including the background process. Unless otherwise specifiedSIGHUP
, the default behavior is to terminate the process. Furthermore, the process’s standard input, output, and error streams may still be connected to the (soon-to-be-closed) terminal, potentially causing problems or unexpected behavior. - Application scenario: Quickly start a task and immediately release the terminal for non-critical background tasks that can be interrupted.
5.2. nohup command: ignore SIGHUP signal
- Working principle:
nohup
The command is used to run a specified command and make it ignoreSIGHUP
the signal. Its syntax isnohup command [arg...]
. When younohup
start a command with , even if you close the terminal that started it, the command will notSIGHUP
exit due to receiving the signal. - Output redirection: By default,
nohup
the command’s standard output (stdout) and standard error (stderr) are redirected to files in the current directorynohup.out
. If the current directory is not writable, it will try to redirect them there$HOME/nohup.out
. You can also redirect the output manually, for examplenohup my_command > my_output.log 2>&1
. - Purpose: Ensure that the process continues to run after you log out or close the terminal.
5.3. Golden combination: nohup command &
- Explanation: Combining
nohup
and&
is the most common way to reliably run a command in the background.nohup command [arg...] &
.nohup
ensures that the command ignoresSIGHUP
the signal,&
then puts the command into the background for execution, returning immediately to the terminal prompt. - Application scenarios: deploy services that need to run for a long time, execute time-consuming batch tasks, and run any program that you want to keep running after you disconnect.
6. Process Behavior: Signal Handling and Default Responses
Now, let’s explore how programs interact with signals internally.
6.1. What happens if a program does not explicitly write signal handling logic?
- Explanation: Very simple, the process will perform the default action for the signal .
- Received
SIGINT
(Ctrl+C
),SIGTERM
(kill <PID>
),SIGQUIT
(Ctrl+\
): The default is usually to terminate the process. - Received
SIGTSTP
(Ctrl+Z
): The default is to pause (suspend) the process. - Received
SIGHUP
(terminal closed): The default is to terminate the process. - Received
SIGKILL
(kill -9 <PID>
): By default, the process is always terminated (cannot be changed). - Received
SIGCONT
(fg
,bg
,kill -CONT <PID>
): The default is to resume the run (if it was previously paused).
- Received
- So, if your script or program does not handle this specially
SIGINT
, pressingCtrl+C
it will exit directly.
6.2. Writing a Signal Handler (Using Python as an Example)
Most programming languages provide a mechanism for handling signals. In Python, you can use the signal handling signal
module.
- Example code 1: Simple Python script, no signal processing
# simple_loop.py
import time
import os
print(f"Process ID: {os.getpid()}")
print("Running a simple loop... Press Ctrl+C to attempt interrupt.")
count = 0
while True:
count += 1
print(f"Loop iteration {count}")
time.sleep(1)
- test:
- run
python simple_loop.py
. - according to
Ctrl+C
.
- Expected behavior: The program terminates immediately and may display
^C
a message like . This is becauseSIGINT
the default behavior of is to terminate the process.
- run

- Example code 2: Python script, capture
# signal_handler_example.py
import signal
import time
import sys
import os
print(f"Process ID: {os.getpid()}")
print("Running loop with SIGINT handler. Press Ctrl+C.")
# Define signal handler function
def graceful_shutdown(signum, frame):
print(f"\nReceived signal {signum} ({signal.Signals(signum).name}). Cleaning up...")
# You can add your cleanup code here, such as saving status, closing files, etc.
print("Performing graceful shutdown steps...")
time.sleep(1) # Simulate cleanup operations
print("Cleanup complete. Exiting.")
sys.exit(0) # Graceful Exit
# Register a handler for SIGINT (Ctrl+C)
signal.signal(signal.SIGINT, graceful_shutdown)
# You can also catch SIGTERM (kill <PID>)
signal.signal(signal.SIGTERM, graceful_shutdown)
count = 0
while True:
count += 1
print(f"Loop iteration {count}. Still running...")
time.sleep(1)
# If you want the loop to end naturally after a certain condition, you can add a judgment here
# if count > 10:
# print("Loop finished normally.")
# break
- test:
- run
python signal_handler_example.py
. - according to
Ctrl+C
.
- Expected behavior: The program will not terminate immediately. Instead, it will print
Received signal 2 (SIGINT). Cleaning up...
a message such as , execute the logic in the handler function, and then callsys.exit(0)
exit.
- Open another terminal, find the PID of the script (the first line of output), and execute
kill <PID>
(sendSIGTERM
).
- Expected behavior: Again, the program will capture
SIGTERM
, executegraceful_shutdown
the function, and then exit.
- run

6.3. How to force quit after catching a signal?
- Explanation: If a process catches
SIGINT
orSIGTERM
and does not choose to exit in its signal handler (or enters an infinite loop or stuck state), thenCtrl+C
orkill <PID>
cannot terminate it. At this time, we need the last resort:SIGKILL
. - Demo:
- Modify the function
signal_handler_example.py
ingraceful_shutdown
so that it is not calledsys.exit(0)
, for example, it only prints a message:
- Modify the function
def stubborn_handler(signum, frame):
print(f"\nReceived signal {signum} ({signal.Signals(signum).name}). Haha, I caught it but I won't exit!")
# ... # You can add other operations here
signal.signal(signal.SIGINT, stubborn_handler)
signal.signal(signal.SIGTERM, stubborn_handler)
# ...
-
- Run the modified script
python signal_handler_example.py
. PressCtrl+C
. You will see it print the message but continue running. Execute in another terminalkill <PID>
. It will still print the message and continue running. Now, executekill -9 <PID>
. Or executeCtrl+\
.
- Expected behavior: The process is immediately and forcefully terminated without any cleanup or goodbye messages. The terminal may display
Killed
. This isSIGKILL
the power of .
- Run the modified script

Forced pause: SIGSTOP
(Signal 19)
- Explanation: Similar
SIGKILL
to the forced termination of ,SIGSTOP
it is a forced pause signal. UnlikeSIGTSTP
(Ctrl+Z
),SIGSTOP
it cannot be caught, blocked, or ignored by the process . You can send it viakill -STOP <PID>
or .kill -19 <PID>
- Use:
SIGTSTP
Use when you want to immediately and unconditionally suspend the execution of a process (even if it is ignored)SIGSTOP
. After the process is suspended, you can useSIGCONT
(kill -CONT <PID>
orkill -18 <PID>
) to resume it. - Keyboard shortcuts: Again, there is no
SIGSTOP
standard keyboard shortcut assigned to .
A tougher interruption: SIGQUIT
(Signal 3) withCtrl+\
- Explanation: As mentioned previously, is
SIGQUIT
typicallyCtrl+\
triggered by . WhileSIGQUIT
it can be caught or ignored by the process (unlikeSIGKILL
/SIGSTOP
), its default behaviorSIGINT
differs from : it not only terminates the process but also typically generates a core dump file . This file is a snapshot of the process’s memory state at the time of termination and is very useful for post-mortem debugging. - Compulsory in practice: Due to the nature of generating core dumps, and
SIGINT
the fact that programs are less likely to specifically capture and handle themSIGQUIT
than , in practice,Ctrl+\
it is oftenCtrl+C
more effective than to terminate some “reluctant” programs. - Use case: When
Ctrl+C
does not work, or you suspect the program crashes and want to get a core dump file to analyze the cause, you can try itCtrl+\
. But remember that it is still not absolutely mandatory, if the process explicitly captures and ignores itSIGQUIT
, it may also be ineffective.
When you need to stop a foreground process, try the following increasing order of force :
Ctrl+C
(SIGINT
) : Attempt graceful termination.Ctrl+\
(SIGQUIT
) : Try a tougher interrupt and possibly get a core dump.Ctrl+Z
(SIGTSTP
) : Pause the process, then you can usekill -9 %job_id
or (need to find the PID with orkill -9 <PID>
first ). For background processes or processes with known PIDs:jobs
ps
kill <PID>
(SIGTERM
) : Request a graceful exit.kill -QUIT <PID>
(SIGQUIT
) : A more forceful exit request, which may generate a core dump.kill -9 <PID>
(SIGKILL
) : Forced termination.
7. Terminal Multiplexer: tmux and Process Management
tmux
It is a powerful tool that allows us to create and manage multiple virtual terminal sessions on a single physical terminal. Its relationship with process lifecycle and signals is worth exploring.
7.1. Introduction to tmux
tmux
Terminal Multiplexer (TM) allows you to have multiple independent shell sessions (windows and panes) within a single window and easily switch between them. Its key feature is session detachment (detach) and reattachment (attach) . You can start atmux
session, run commands within it, thendetach
close your SSH connection or physical terminal, andattach
return to it later to find your programs still running.
7.2. Effects of tmux exiting the current window/pane on the process
Here we need to strictly distinguish several tmux
ways of “exit”:
- Detach: This is usually done using the shortcut key
Ctrl+B
and then pressingd
. This simply disconnects your client (your current terminal) fromtmux
the server.tmux
The server itself, along with all sessions, windows, panes, and processes it manages, continues to run in the background .detach
No signals are sent totmux
processes running within it. You can reconnect usingtmux attach
or .tmux a
- Close the pane/window (Exit/Kill):
- In the Shell window of the pane, type
exit
or pressCtrl+D
: This will end the Shell process. If this Shell is the only process in the pane, the pane will close. - Use
tmux
command:tmux kill-pane
ortmux kill-window
. - Effect on processes: When a pane or window is closed, a signal
tmux
is normally sent to the foreground process group in that pane/windowSIGHUP
. This behavior is similar to closing a normal terminal. Therefore, if the foreground process in the pane has no handlesSIGHUP
or was notnohup
started with , it will likely be terminated.
- In the Shell window of the pane, type
7.3. Running services inside tmux
Suppose you tmux
have a service (such as a web server) running in a pane of the window:
- If the service is running in the foreground (eg,
python my_web_server.py
) :- You
detach
(Ctrl+B d
): The service continues to run .tmux
The server and the session are both up. - You enter in this pane
exit
orCtrl+D
(close the pane):tmux
may bepython my_web_server.py
sent toSIGHUP
. If this Python server does not catch and handleSIGHUP
(the default behavior is to terminate), then the server will stop .
- You
- If the service has been correctly backed/daemonized (eg,
nohup python my_web_server.py &
, or the service has daemonization logic implemented within it) :- You
detach
: The service continues to run . exit
You enter or in this paneCtrl+D
: Even iftmux
sentSIGHUP
, the service will continue to runnohup
because the process was started with (ignoredSIGHUP
) or has been detached from the terminal (daemonized) . Closing this pane has no effect on it.
- You
7.4. Sample code testing in tmux scenario
Let’s use the previous Python script tmux
to experiment in the environment:
- To start
tmux
: Type in your terminaltmux
. - Test
Ctrl+C
(SIGINT):tmux
Runs in a pane (python simple_loop.py
no signal handling).- Press
Ctrl+C
. Expected: process terminates, just like in a normal terminal. tmux
Run in a pane (python signal_handler_example.py
catch SIGINT).- Press
Ctrl+C
. Expected: Execute signal handler, then exit (or act as per handler logic).
- Test
detach
andattach
:tmux
Run in a pod (python simple_loop.py &
run in the background, but nothingnohup
). Note the PID.detach
Session (Ctrl+B d
).- Go back to the normal terminal and check with
ps aux | grep python
orps -p <PID>
. Expected: the process is still running. attach
Return to the session (tmux attach
).- You can use
fg
to bring the background task back to the foreground and thenCtrl+C
stop it, or usekill <PID>
.
- Test closing the pane (simulating SIGHUP):
tmux
Run in a pane (python simple_loop.py
foreground, no signal handling, nothingnohup
). Note the PID.tmux
Type in the paneexit
or press toCtrl+D
close the pane.- Go back to the other terminal (
tmux
or other pane/window of ) and check withps aux | grep python
orps -p <PID>
. Expected: The process has most likely terminated because it receivedSIGHUP
and the default behavior is to exit.
- Test closing the pane (using
nohup
):tmux
Run in the pod .nohup python simple_loop.py &
Note the PID.tmux
Type in the paneexit
or press toCtrl+D
close the pane.- Go back to the other terminal and check with
ps aux | grep python
orps -p <PID>
. Expected: The process is still running , but because it isnohup
protected by , it is ignoredSIGHUP
. The output will go tonohup.out
the file.


8. Summary
We’ve delved into the signal mechanism, the core of Linux/Unix process control. Understanding the meaning and default behavior of key signals such as SIGINT
, SIGTERM
, SIGKILL
, SIGHUP
, and , SIGTSTP
is crucial. We’ve seen how Ctrl+C
and Ctrl+Z
interact with foreground processes through signals, and learned how to use kill
and pkill
to send signals to processes precisely or in batches. The combination of &
and nohup
ensures reliable background execution. Finally, we analyzed tmux
the process lifecycle in a [unclear context – likely a corrupted or corrupted file] environment, specifically detach
the different effects of and closing a window on a process. Mastering this knowledge will empower you to be more proficient in development and operations, write more robust programs, and effectively manage system resources.
9. Appendix
- List of commonly used signals (partial):
- 1:
SIGHUP
(Hangup) - 2:
SIGINT
(Interrupt) - 3:
SIGQUIT
(Quit) - 9:
SIGKILL
(Kill) - 15:
SIGTERM
(Terminate) - 18:
SIGCONT
(Continue) - 19:
SIGSTOP
(Stop – cannot be caught or ignored) - 20:
SIGTSTP
(Terminal Stop)
- 1:
- Related Commands
man
Manual Page Reference:man 7 signal
(Detailed signal description)man 1 kill
man 1 pkill
man 1 nohup
man 1 tmux
man 2 signal
(Programming interface)man ps
man jobs
,man fg
,man bg