So, we have the job ID, process ID, foreground, and background processes, but how do we control these jobs? We have a bunch of commands available, let's have a look at how to use them:
- kill: We can pass the job ID to this command, which will send the SIGTERM signal to all the processes belonging to the job itself:
zarrelli:~$ sleep 100 &
[1] 9909
zarrelli:~$ kill %1
zarrelli:~$
[1]+ Terminated sleep 100
You can also pass to kill a specific signal to send to the process. For instance, kill -15 will nicely terminate a process with a SIGTERM signal, and if it refuses to die, kill -9 will send a SIGKILL, which will instantly terminate a process.
Which signals can we send to a process? Either kill -l or cat /usr/include/asm-generic/signal.h will give us a list of all the signals supported.
- killall: If we know what is the name of the process, the easiest way to kill it is through the killall command followed by the name of the process:
zarrelli:~$ sleep 100 &
[1] 10595
zarrelli:~$ killall sleep
[1]+ Terminated sleep 10
But killall has another interesting to use. Let's run the sleep command for four times, each time with a different argument:
zarrelli:~$ sleep 100 &
[1] 10672
zarrelli:~$ sleep 200 &
[2] 10689
zarrelli:~$ sleep 300 &
[3] 10690
zarrelli:~$ sleep 400 &
[4] 10693
Now, let's check the list of processes:
zarrelli:~$ ps -jf
UID PID PPID PGID SID C STIME TTY TIME CMD
zarrelli 1422 1281 1422 1422 0 08:46 pts/0 00:00:00
/bin/bash
zarrelli 10672 1422 10672 1422 0 11:16 pts/0 00:00:00 sleep
100
zarrelli 10689 1422 10689 1422 0 11:16 pts/0 00:00:00 sleep
200
zarrelli 10690 1422 10690 1422 0 11:16 pts/0 00:00:00 sleep
300
zarrelli 10693 1422 10693 1422 0 11:16 pts/0 00:00:00 sleep
400
zarrelli 10699 1422 10699 1422 0 11:16 pts/0 00:00:00 ps -jf
We can see the four processes: same name and different argument. Now, let's use killall giving the process name, sleep, as its argument:
zarrelli:~$ killall sleep
[1] Terminated sleep 100
[2] Terminated sleep 200
[4]+ Terminated sleep 400
[3]+ Terminated sleep 300
All the processes have been killed at once. Quite handy, isn't it? Let's make the last check:
zarrelli:~$ ps -jf
UID PID PPID PGID SID C STIME TTY TIME CMD
zarrelli 1422 1281 1422 1422 0 08:46 pts/0 00:00:00
/bin/bash
zarrelli 10709 1422 10709 1422 0 11:16 pts/0 00:00:00 ps -jf
No more instances of sleep running now; we killed everything with one single run of killall.
- jobs: This shows the processes running in the background along with their job ID:
zarrelli:~$ sleep 100 &
[1] 8892
zarrelli:~$ sleep 200 &
[2] 8893
zarrelli:~$ jobs
[1]- Running sleep 100 &
[2]+ Running sleep 200 &
- fg: This sends a background running job to the foreground. It accepts the job ID as an argument. If no job ID is provided, the current job is affected:
zarrelli@moveaway:~$ sleep 100 &
[1] 9045
zarrelli@moveaway:~$ fg %1
sleep 100
- bg: This sends a foreground job to the background. If no job ID is provided, the current job is affected.
- suspend: This suspends the shell until a SIGCONT signal is received.
- logout: This logs out from the login shell.
- disown: This removes a job from the shell table of active jobs.
- wait: This interesting command stops the execution of a script until all the background jobs have terminated or, if passed as an argument, until a job ID or a PID terminates, and returns the exit status of the process it was waiting for.
Job ID |
Meaning |
Example |
%n |
Job number |
Kill %1 |
%s |
String the command executed starts with |
sleep 200 & [1] 9486 kill %sl [1]+ Terminated sleep 200 |
%?s |
String the command executed contains |
sleep 200 & [1] 9504 kill %?ee [1]+ Terminated sleep 200 |
%% |
Last job that has been either stopped in the foreground or started in the background |
sleep 200 & [1] 9536 kill %% [1]+ Terminated sleep 200 |
%+ |
Last job that has been either stopped in foreground or started in the background |
sleep 200 & [1] 9618 fg %+ sleep 200 |
%- |
Last job |
sleep 200 & [1] 9626 kill %- [1]+ Terminated sleep 200 |
$! |
Last process in the background |
sleep 200 & [1] 9646 sleep 300 & [2] 9647 sleep 400 & [3] 9648 kill $! [3]+ Terminated sleep 400 |
- times: We saw this command at the opening of this book. It gives us statistics on time elapsed during the execution of a command.
- builtin: This execute a builtin command disabling functions and non-builtin commands, which have the same name as the builtin.
- command: This disables all the aliases and functions for the specified command:
zarrelli@moveaway:~$ ls
Desktop Documents Downloads First session Music Pictures
progetti Projects Public Templates tmp Videos
[1]- Done sleep 200
[2]+ Done sleep 300
zarrelli:~$ ls
Desktop Documents Downloads First session Music Pictures
progetti Projects Public Templates tmp Videos
zarrelli:~$ alias ls="ps -jf"
zarrelli:~$ ls
UID PID PPID PGID SID C STIME TTY TIME CMD
zarrelli 1373 1267 1373 1373 0 07:36 pts/0 00:00:00
/bin/bash
zarrelli 10738 1373 10738 1373 0 10:17 pts/0 00:00:00 ps -jf
zarrelli:~$ command ls
Desktop Documents Downloads First session Music Pictures
progetti Projects Public Templates tmp Videos
zarrelli@moveaway:~$ ls
UID PID PPID PGID SID C STIME TTY TIME CMD
zarrelli 1373 1267 1373 1373 0 07:36 pts/0 00:00:00 /bin/bash
zarrelli 10742 1373 10742 1373 0 10:17 pts/0 00:00:00 ps -jf
- enable: This enables or disables the -n builtin command, so if we have a builtin and an external command, then when invoked, the builtin will be ignored and the external command will be executed. Specifying the -a option will show a list of all the builtins along with their status, while the -f switch will load a builtin as a shared library module from a compiled object file.
- Autoload: This is not enabled by default in Bash and it must be loaded through enabling -f. It marks a name as a function name and not a builtin or an external command reference. The named function must reside in an external file and it will be loaded from there.
So, we had a look at the foreground and background processes and at the job controlling commands; now, we can see how to work with subshells and what benefit they can bestow on our scripts.