The jobs command is a Bash builtin that lists all background and suspended processes belonging to the current shell session. It shows the job number, state, and command for each job, and works together with fg, bg, kill, and disown to give you full control over those processes.
The syntax is:
bashjobs [OPTIONS] [JOB_SPEC...]
Run without arguments to see all active jobs:
bashjobs
Sample output with two jobs — one stopped and one running:
[1]- Stopped vim notes.txt[2]+ Running ping google.com &
Each line shows four things: the job number in brackets, a + or - marker, the job state, and the command that started the job.
The + marks the current job – the one that fg and bg will act on by default when no job spec is given. The - marks the previous job. When the current job finishes, the previous job becomes the new current job.
Job states:
Done is worth noting: the shell does not display it immediately. You see it the next time you press Enter or run another command.
Add PIDs to the output with -l:
bashjobs -l
The PID is shown between the marker and the state. Useful when you need to signal a specific process with kill.
Other options:
-r – list only running jobs-s – list only stopped jobs-p – print only the PID of each job’s process group leader-n – show only jobs whose status changed since the last notificationJob specifications (job specs) let you target a specific job in fg, bg, kill, and disown. They always start with %:
| Spec | Targets |
|---|---|
%1, %2 | Job by number |
%+ or %% | Current job (marked with +) |
%- | Previous job (marked with -) |
%string | Job whose command starts with that string |
%?string | Job whose command contains that string anywhere |
The difference between %string and %?string matters when the keyword appears mid-command. %ping matches a job started with ping google.com. %?google also matches it because “google” appears anywhere in the command.
Bring job 1 to the foreground by number or prefix — both work:
bashfg %1fg %sleep
Remove a job from the shell’s job table so it survives terminal close:
bashdisown %1
After disown, the shell no longer tracks the job and will not send SIGHUP to it when the terminal closes.
Job control is disabled by default in shell scripts. Running jobs inside a script returns nothing, even when background processes exist. In scripts, use $! to capture the PID of the last backgrounded command, then use wait with the PID:
bashlong_task &task_pid=$!# Check if the process is still runningwhile kill -0 "$task_pid" 2>/dev/null; do echo "Still running..." sleep 5doneecho "Done."
kill -0 sends no signal. It only checks whether the process exists. Exit code 0 means it is running; any other exit code means it has stopped.
To wait for several parallel background tasks before continuing:
bashtask_a & pid_a=$!task_b & pid_b=$!wait "$pid_a" "$pid_b"echo "Both complete."
To keep a job alive after closing the terminal, use nohup before starting it or disown after backgrounding it. For long-running interactive sessions, screen or tmux are better choices.
Use jobs to see what is running in your shell, job specs with % to target them, and $! with wait when writing scripts. Leave a comment below if you run into any issues.
The Linux kernel writes messages to the kernel ring buffer throughout the boot process and…
rsync over SSH combines secure encrypted transport with fast incremental transfers. Instead of copying every file…
The pstree command in Linux displays running processes in a tree structure rather than a flat list.…
The type command in Linux shows how the current shell would interpret a name typed on the…
When a Linux system is slow or behaving unexpectedly, memory is one of the first…
The ip command is the standard network configuration tool on modern Linux systems. It is part of…