Job IDs, PIDs & Session IDs

GNU Screen & Linux Job Control

Chapter 6 · Job IDs, PIDs & Session IDs: Telling Them Apart

By now you've met several kinds of number: [1] when a job starts, 48213 next to it, the 24817 at the front of a screen session ID, and window numbers inside a session. They're easy to mix up, and using the wrong one with kill can end the wrong thing. This chapter sorts them out and shows how to find any process, including one hidden inside a screen session.

Four Numbers, Four Scopes

NumberExampleWho assigns itWhere it's valid
Job number%1Your shellOnly in the shell that started the job
Process ID (PID)48213The Linux kernelSystem-wide, for as long as the process exists
Screen session ID24817.backupScreen (the PID of its server, plus a name)For your user, through screen's commands
Window number2ScreenOnly inside that one session

Only the PID means something to the kernel. The other three are labels kept by a particular program: the shell, or screen. That's why kill 48213 works from any terminal, but kill %1 only works in the shell that owns job 1.

One Job, Several Processes

A job isn't always one process. A pipeline such as cat big.log | grep ERROR | sort is a single job made of three processes, each with its own PID. The shell groups them into a process group, and the job's commands act on the whole group: Ctrl-Z or kill %1 reaches all three.

$ cat big.log | grep ERROR | sort > errors.txt & [1] 50122 # bash shows the PID of the last process in the pipeline $ jobs -l [1]+ 50120 Running cat big.log 50121 | grep ERROR 50122 | sort > errors.txt &

Getting PIDs From the Shell

CommandGives you
jobs -lThe job list with the PID of every process in each job
jobs -pJust the PIDs (one per job, for a pipeline the group leader)
$!The PID of the most recent background job
$$The PID of the current shell itself
# Save the PID of a background job for later ./import.sh > import.log 2>&1 & IMPORT_PID=$! echo "Import running as PID $IMPORT_PID"

Finding Processes With ps and pgrep

Outside the shell that started them, you find processes with system tools instead of jobs.

# All your processes, with parent PID, group, terminal and state ps -u $USER -o pid,ppid,pgid,tty,stat,cmd # Find processes by name, showing their full command line pgrep -a sleep # Match against the whole command line, not just the program name pgrep -af "import.sh"
STAT letterMeaning
RRunning (or ready to run)
SSleeping, waiting for something
TStopped — for example after Ctrl-Z
ZZombie: finished, but its parent hasn't collected it yet
+In the foreground process group of its terminal

Finding a Process Inside a Screen Session

Every process in a session is a descendant of that session's SCREEN server process, whose PID is the number at the front of the session ID (Chapter 3). So pstree can show you exactly what a session is running:

$ screen -ls 24817.backup (Detached) $ pstree -p -a 24817 SCREEN,24817 -S backup ├─bash,24818 │ └─rsync,24901 -a /data /mnt/backup └─bash,25003 └─top,25010

This session has two windows: one running rsync and one running top. The -p option shows PIDs and -a shows command-line arguments.

The Reverse: Which Session Is This Process In?

Sometimes you find a PID with pgrep and want to know which session it lives in. Walk up its parents with pstree -s:

$ pstree -s -p 24901 systemd(1)───SCREEN(24817)───bash(24818)───rsync(24901)

The SCREEN(24817) ancestor tells you it's in session 24817. Two environment variables that screen sets for every window give the same information from the inside:

# Inside a window echo $STY # session ID, e.g. 24817.backup echo $WINDOW # window number, e.g. 0 # From outside, for one of your own processes tr '\0' '\n' < /proc/24901/environ | grep -E '^(STY|WINDOW)='
Environment variables are a snapshot
/proc/PID/environ shows the environment the process started with. If a process was started elsewhere and later moved into screen (Chapter 8), it won't have STY set, so trust the pstree -s ancestry instead.

Hands-On Exercises

Exercise 1

Start sleep 1000 | cat &. Find its job number, the PID of each process in it, and the PID of your shell. Then open a second terminal and end the job from there. Why can't you use %1 in the second terminal?

📄 View solution
Exercise 2

Create a detached session named jobs with two windows, one running sleep 2000 and one running top. Without attaching, use screen -ls and pstree to show what's running inside it.

📄 View solution
Exercise 3

Using pgrep, find the sleep 2000 process from Exercise 2, then prove which screen session and window it belongs to in two different ways.

📄 View solution

Chapter 6 Quick Reference

  • Job numbers belong to one shell; PIDs are system-wide; session IDs and window numbers belong to screen
  • A job can contain several processes (a pipeline), grouped into one process group
  • jobs -l shows PIDs, jobs -p only PIDs; $! is the last background PID, $$ the shell's own
  • ps -o pid,ppid,pgid,tty,stat,cmd and pgrep -a/-af find processes; STAT T means stopped
  • pstree -p -a SCREEN_PID shows everything in a session; pstree -s -p PID shows a process's ancestors
  • Inside screen, $STY is the session ID and $WINDOW the window number