It's an old question and there are already few good answers, but, I'll try to present mine in a little different way.
Actually, backgrounded processes are called jobs, and job control is very well explained in those 3 short pages: https://www.gnu.org/software/bash/manual/html_node/Job-Control.html
Basically, we can reference a job by a jobspec, that is the symbol %
follow either by another symbol (or a sequence in some fancier cases), or by a job ID. And it's the same for kill
, fg
, bg
or disown
.
%+
(or just %
, or %%
) will reference the latest backgrounded
job (current)
%-
will reference the previous one
%{jobid}
will reference the specified job
To list your backgrounded jobs, you use the command jobs
.
Note
kill $!
has a different behavior, it will kill the latest process sent in the background as a job, and not the latest job created.
e.g
You have sent 5 jobs in the background.
You bring back job #2 in the foreground (fg %2
, or just %2
), then sent it back in the background (<Ctrl-Z>
, then bg
).
It is the latest process sent to the background, but it remains job #2.
So that kill $!
will terminate job #2 - the latest process (re)sent to the background, while kill %+
will kill job #5, the latest job that have been created ("current job"):
$ jobs
[1] Running sleep 1000 &
[2] Running sleep 2000 &
[3] Running sleep 3000 &
[4]- Running sleep 4000 &
[5]+ Running sleep 5000 &
$ fg %2
sleep 2000
^Z
[2]+ Stopped sleep 2000
$ bg
[2]+ sleep 2000 &
$ jobs
[1] Running sleep 1000 &
[2] Running sleep 2000 &
[3] Running sleep 3000 &
[4]- Running sleep 4000 &
[5]+ Running sleep 5000 &
$ kill %+
$ jobs
[1] Running sleep 1000 &
[2] Running sleep 2000 &
[3] Running sleep 3000 &
[4]- Running sleep 4000 &
[5]+ Terminated sleep 5000
$ kill $!
[2] Terminated sleep 2000
$ jobs
[1] Running sleep 1000 &
[3]- Running sleep 3000 &
[4]+ Running sleep 4000 &