Every Linux user eventually discovers the nuclear option kill -9 -1
which terminates all processes owned by the current user. However, this includes your current terminal session - essentially cutting the branch you're sitting on. Here's why this happens:
# This terminates EVERYTHING including your terminal:
kill -9 -1
The solution involves intelligent process filtering. We'll use pgrep
to identify processes while excluding:
- The current shell process ($$)
- The terminal emulator process
- Any critical session managers
Here's the most robust implementation I've used in production environments:
#!/bin/bash
# Get current terminal PID and parent terminal process
TERM_PID=$(ps -o ppid= -p $$)
SHELL_PID=$$
# Kill all user processes except these
kill -9 $(pgrep -u $USER | grep -vw -e $SHELL_PID -e $TERM_PID -e $(pgrep -P $TERM_PID))
For different use cases, consider these approaches:
# Method 1: Using pkill with exclusions
pkill -u $USER -P 1 --signal SIGKILL -v -P $$
# Method 2: Using procfs directly
kill -9 $(ls /proc/ \
| grep '^[0-9]' \
| awk -v me=$UID -v shell=$$ '$1 != shell && $1 != PPID {print $1}' \
| xargs -r ps -o pid= -p 2>/dev/null)
Always test with -SIGTERM
first before using -SIGKILL
:
# Dry run first
pkill -u $USER -P 1 --signal SIGTERM -v -P $$
# Then force kill if needed
pkill -9 -u $USER -P 1 -v -P $$
If you're working with tmux or screen sessions, modify the exclusion pattern:
# Preserve tmux/screen sessions
SCREEN_PID=$(ps -o ppid= -p $(pgrep -u $USER tmux\\|screen))
kill -9 $(pgrep -u $USER | grep -vw -e $$ -e $TERM_PID -e $SCREEN_PID)
Many Linux users discover the kill -9 -1
command as a quick way to terminate all their processes. However, this nuclear option has an obvious drawback - it kills the terminal session itself, making it impractical for interactive use.
Here's a safer approach that preserves your current terminal while terminating other processes:
# Get current terminal's process ID
CURRENT_TERM=$(ps -p $$ -o ppid= | tr -d ' ')
# Kill all user processes except current terminal and its children
pkill -u $USER -P 1 -v -P $CURRENT_TERM
This approach works by:
- Identifying the parent process ID (PPID) of your current terminal session
- Using pkill with the
-v
(invert match) flag to exclude processes with that PPID - The
-P 1
ensures we target processes initiated by the user
For systems without pkill, you can use this killall alternative:
# Get current shell's process tree
CURRENT_TREE=$(pstree -p $$ | grep -o '[0-9]\+' | tr '\n' ',' | sed 's/,$//')
# Kill all user processes not in the current tree
killall -u $USER -r -v "($CURRENT_TREE)"
To make this command easily accessible, add this to your ~/.bashrc
:
alias killother='pkill -u $USER -P 1 -v -P $(ps -p $$ -o ppid= | tr -d " ")'
- This will terminate all background jobs, SSH sessions, and detached processes
- Running GUI applications may be affected depending on your desktop environment
- Always test in a non-production environment first
For systems with unusual process hierarchies, you might need to adjust the parent process filtering. This version handles more complex cases:
# Get entire process ancestry
TERM_ANCESTORS=$(pstree -ps $$ | grep -o '[0-9]\+' | tr '\n' '|' | sed 's/|$//')
# Kill everything except ancestry
pgrep -u $USER | grep -vE "($TERM_ANCESTORS)" | xargs kill -9