Bash Jobs#

When you start a program from the commandline with bash, you can do all sort of things while the program is still running.

If you press Ctrl-Z the program will be suspended. Press Ctrl-Y and it will only be suspended when the program attempts to read from stdin. You can then either continue with the command fg or let it run in the background with bg.

I think it’s one of the easiest ways to run multiple things at once.

Note

When running an interactive shell, the shell is running in monitor mode which allows job control. You can set this with set -m or disable it with set +m.

Note

If you don’t redirect the output of your command, you’ll still see the output even when the program is running in the background. You can prevent this behavior by executing stty tostop which causes the background job to stop when it tries to write to the terminal. You can turn this behavior off again with stty -tostop.

Running something in the background can be done immediately by adding an & right after the command when you’re typing inside an interactive shell or writing a bash script.

jobs#

The jobs command is used to the print the statusses of jobs that haven’t been completed.

$ jobs
[3] + Running   make build &
[2] - Running   monitor &
[1]   Running   run program > /tmp/output &

You can also see the process ID’s in this list with jobs -l. If you only want the process ID’s (which is handy for other commands), use jobs -p.

The + and - after the job number mark the current and previous jobs. The current job is the job most recently sent to the background, and the previous job is the next-to-the-last- job sent to the background.

You can refer to a job (for example when executing fg) with a job specification, which start with a %. A number like %1 refers to job 1, %% and %+ refers to the current job, %- refers to the previous job, %substring refers to the job whose command start with substr (or returns an error when more than 1 job matches) and %?substr refers to the job who has the substr anywhere in the command (or returns an error when more than 1 job matches).

Only naming a job like %1 brings it to the foreground for execution. %1 & or bg %1 brings it to the background and resumes execution there.

jobs -x ''cmd args'' replaces the given jobspec with a process ID.

Sending signals#

When programs run in the foreground, keyboard-generated signals like SIGNINT triggered by Ctrl-C are send to the program.

To send a signal to a background job, use kill. By default this sends a SIGTERM signal. You can specify the signal to be send with a signal name or number right after the kill command. To send SIGKILL to one of the background jobs, use the jobs specifications like kill -KILL %1, kill -9 %-, etc or process ID’s.

You could also send a signal to multiple jobs by just listing them like kill %1 %2 %3. Or send a signal to them all by using jobs again and their process ID’s like kill `jobs -p`.

You could also use jobs -x kill %% to send the default signal to the current job, because jobs -x will replace job specifications argument to process ID’s.

wait#

When you have multiple jobs running in the background, you might want to wait for some to actually finish. Instead of watching the job statuses with jobs, use the wait command. Without parameters, wait waits for all currenctly active child processes.

If you want to wait for a particular job, you can use it’s job specification or process ID as an argument. wait will return the exit status of that specific job.

If you want to wait for the first finished job of all the jobs running in the background, use -n so you can get the next job and it’s exit status.

wait only returns when the status of the job is changing. When you’re in the terminal, you can use -f to wait until the job/process actually terminates.

More#

  • Use set -b to immediately report the status of terminated background jobs

  • any trap on SIGCHLD is executed for each child process that exits

  • shopt checkjobs list status of any stopped and running jobs before exiting an interactive shell. If you try to exit the interactive shell a second time, it will be executed and the jobs are terminated.