This lesson explains how Linux runs programs and how to manage them from the shell. It covers listing and filtering processes, shell job control, signals, foreground and background execution, persistence across logout, priority tuning with nice
and renice
, and quick inspection methods.
Process is a running program with a PID. Job is a process or pipeline started from the current shell and tracked by that shell. Signal is a message sent to a process to request an action such as terminate or reload.
Prerequisites
Listing and filtering processes
# snapshot of processes for current user
ps -u "$USER" -o pid,ppid,tty,stat,cmd --sort=pid | head -20
# full system view in BSD style
ps aux | head -20
# tree view to see parents and children
ps axjf | head -30
# find by name or user
pgrep -a ssh
pgrep -u "$USER" -l bash
# list PIDs and commands owned by a user\pps -U "$USER" -o pid,stat,comm --sort=pid | column -t | head
top
gives an updating view. Press q
to quit.
top
Useful keys inside top
:
P
sort by CPU,M
sort by memoryk
send signal to a PID, default is SIGTERMu
filter by user,o
add a filter likeCOMMAND=ssh
1
toggle per CPU display
htop
is friendlier when installed.
sudo apt install -y htop 2>/dev/null || sudo dnf install -y htop 2>/dev/null
htop
Job control in the shell
Start a long running command in the background with &
.
sleep 60 &
jobs -l
Suspend a foreground job with Ctrl Z
, then continue it.
# start a long command
sleep 300
# press Ctrl Z to suspend
bg %1 # continue in background
jobs
fg %1 # bring back to foreground
Numbered jobs use the %
prefix. jobs -r
shows running jobs. jobs -s
shows stopped jobs.
A job is attached to the shell that started it. Closing the terminal usually sends SIGHUP and ends the job unless it is protected with nohup
or detached with disown
.
Foreground, background, and persistence
# run immune to hangup and log output to a file
nohup long_task.sh > long_task.log 2>&1 &
# detach an already running job from the shell's job table
disown %1
nohup
makes the process ignore SIGHUP and writes output to nohup.out
if redirection is not set.
Foreground processes read from the controlling terminal. Background processes that try to read from the terminal receive SIGTTIN and stop. Redirect input from a file if needed.
Signals and safe termination
Common signals:
- SIGTERM 15 ask a process to exit cleanly
- SIGKILL 9 force kill without cleanup
- SIGHUP 1 request reload or hangup depending on the program
- SIGINT 2 interrupt, same as
Ctrl C
Send signals by PID or by name.
# by PID
kill -TERM 12345
kill -KILL 12345 # last resort
# by name or pattern
pkill -TERM -u "$USER" sleep
killall -v firefox 2>/dev/null || true
Check that a PID exists.
kill -0 12345 && echo "running" || echo "not running"
SIGKILL prevents cleanup and may leave temporary files or locks. Prefer SIGTERM, wait a few seconds, then use SIGKILL only if the program fails to exit.
Understanding process states and stats
ps
shows a state code in the STAT column.
R
running,S
sleeping,D
uninterruptible sleep,T
stopped,Z
zombie- a trailing
+
means the process is in the foreground process group of the terminal
Quick CPU and memory usage by PID.
ps -p 1,2,3 -o pid,stat,%cpu,%mem,cmd
Measure a command's resource use.
/usr/bin/time -v sleep 2
Monitor output repeatedly.
watch -n 2 'ps -o pid,%cpu,%mem,cmd -C sshd'
Priority and niceness
Niceness ranges from -20 to 19. Lower is higher priority. Normal users can only increase niceness. Root can decrease it.
Start a program with a given niceness.
nice -n 10 ./cpu_heavy_task
Change an existing process.
# show PID then adjust priority
pgrep -a cpu_heavy_task
sudo renice -n 15 -p <PID>
Use positive niceness for background or batch tasks to keep the desktop responsive. Avoid negative niceness unless there is a clear, measured need.
Quick inspection under /proc
Each PID has a directory under /proc
.
# replace 1 with a real PID
PID=1
ls -l /proc/$PID
ls -l /proc/$PID/fd | head
cat /proc/$PID/cmdline | tr '\0' ' ' && echo
cat /proc/$PID/status | head -20
readlink -f /proc/$PID/exe
readlink -f /proc/$PID/cwd
List processes holding a file or port with lsof
when installed.
sudo apt install -y lsof 2>/dev/null || sudo dnf install -y lsof 2>/dev/null
sudo lsof /var/log/syslog 2>/dev/null | head
sudo lsof -i :22 2>/dev/null
pstree
shows ancestry as a tree.
sudo apt install -y psmisc 2>/dev/null || sudo dnf install -y psmisc 2>/dev/null
pstree -ap | head -30
Practical lab
The lab builds confidence with process discovery and control.
- Start a long lived program and manage it as a job.
sleep 600 &
jobs -l
fg %1 # bring to foreground
# press Ctrl Z
bg %1
- Start a CPU heavy workload and adjust its niceness.
# simple CPU burner
yes > /dev/null &
pgrep -a yes
renice -n 15 -p $(pgrep -n yes)
- Send signals and observe behavior.
PID=$(pgrep -n yes)
kill -TERM "$PID"
# if still running after a few seconds
kill -KILL "$PID"
- Keep a program alive across logout.
nohup bash -c 'for i in $(seq 1 5); do date; sleep 10; done' > ~/nohup-demo.log 2>&1 &
disown %+
- Inspect a process in /proc.
PID=$$ # current shell
cat /proc/$PID/cmdline | tr '\0' ' ' && echo
readlink -f /proc/$PID/exe
ls -l /proc/$PID/fd | head
Troubleshooting
Operation not permitted
when lowering niceness. Only root can set negative niceness values.no job control in this shell
appears in non interactive shells or when job control is disabled. Use an interactive terminal.- A background process keeps stopping with
Stopped (tty input)
. Redirect input from/dev/null
or a file. kill
reports no such process. The PID may have already exited. Refresh withpgrep
orps
.nohup
creatednohup.out
in an unexpected directory. Run the command from the desired working directory or set explicit redirection.
Next steps
Day 8 introduces package management across major distributions. It explains repositories, indexes, signatures, and the commands used to search, install, remove, and update software with apt
, dnf
, and pacman
. It also covers cleaning caches and verifying package provenance.