Job control is a really useful part of bash. You can suspend and resum processes with it without breaking them.
So let's take a look at what this exactly is.
Jobs in bash
First off we need to list current jobs. Jobs are tied to their parent terminal (or bash to be exact), so each terminal can only see jobs created by themselves. To list the created jobs type:
jobs
if it gives back an empty response, that means there are no jobs in that terminal. If you do have jobs it will give back something like:
[1]+ Stopped locate *.png
where:
[1]
is the ID of that jobStopped
is the state of that joblocate *.png
is the command
Creating jobs
There are several ways you can create a job, we'll discuss 2 of them
1. Suspending a process
If there is a long running process, you can press CTRL + Z
and the process becomes suspended. It will be added to the jobs list, with the stopped state. From here you can use fg
to return the process to the foreground, or bg
to bring the process to the background. After you do that the job will be in Running
state. When it finishes it will be in Done
state.
2. Starting process in background
Let's take the locate *.png
command and start it in the background like:
locate *.png &
the &
sign starts the process by default in the background and adds it to the jobs list, with Running
state
Switching the context of jobs.
You can bring foreground processes to background, and background processes to foreground.
First find the ID of the job by jobs
and look at the number for example:[1]
.
Now simply type fg %1
to bring the process ot the foreground and bg %1
to bring the process to the background.
%
means that we're refering to the ID of a job.
Killing a job
If you don't want to wait for the job to exit, you can kill it manually.
Using the kill
command with the same parameters as before like:
kill %1
to kill the first job in that list, this will set the job in Terminated
state.
Another option is to bring the process to the foreground and then use the regular CTRL + C
combination.
Dealing with SIGHUP
SIGHUP is sent to the terminal's jobs, when the terminal is about to close.
This will affect our background jobs and they will stop. However we can do something about that.
nohup
nohup ignores SIGHUPs and keeps the background job running until another signal like SIGKILL or SIGTERM is sent to the process/job. You can use nohup like so:
nohup ping youtube.com &
, this will create a new job starting the nohup process, and nohup ignores the SIGHUP, while it executes the given command. But this is only an option when you know at the starting of the process that you're going to close the terminal. If you don't know it, there's an option for you too!
disown
Disown achives the same as nohup, but it can do it while a job is started. To do this, get the ID of your job and type:
disown -h %1
Disown by default removes the job from the job control, and we don't want to do that until the terminal closes. The -h
option solves exactly this, it only removes the job from the job control when a SIGHUP is detected.
Impotant: If the output of the process isn't redirected to a file for example, then the output of the process will get lost when you close the terminal.
Note: To stop a job that's not listed on the job control, you need to locate the PID of that job an use kill [PID]
to terminate it.
Summary
Job control is a powerful feature in bash, for example if you have an application, that blocks the input (a server application not running as a daemon) you can press CTRL + Z
and type bg
to get back your prompt and keep the server alive. You can also use disown to keep the server alive after closing the terminal.
Now go suspend some processes and background them!
Nice tut, have an updoot