Ctrl-C with two simultaneous commands in bash
If you type
command 1 & command 2
this is equal to
command 1 &
command 2
i.e. this will run the first command in background and then runs the second command in foreground. Especially this means, that your echo "done"
is printed after command 2
finished even if command 1
is still running.
You probably want
command 1 &
command 2 &
wait
echo "done"
This will run both commands in background and wait for both to complete.
If you press CTRL-C this will only send the SIGINT signal to the foreground process, i.e. command 2
in your version or wait
in my version.
I would suggest setting a trap like this:
#!/bin/bash
trap killgroup SIGINT
killgroup(){
echo killing...
kill 0
}
loop(){
echo $1
sleep $1
loop $1
}
loop 1 &
loop 2 &
wait
With the trap the SIGINT signal produced by CTRL-C is trapped and replaced by the killgroup
function, which kills all those processes.
When putting a command into the background from a script, the PID is not displayed on the screen. You can use the builtin variable $!
which stores the PID of the last process so you can capture the PID of command1.
command1 &
echo $!
would echo the PID of command1.
Bash also provides the trap builtin which you can use to register a sequence of commands to run when particular signals are received. You can use this to catch the SIGINT and kill command1 before exiting the main script e.g.
#!/bin/bash
onINT() {
echo "Killing command1 $command1PID too"
kill -INT "$command1PID"
exit
}
trap "onINT" SIGINT
command1 &
command1PID="$!"
comamnd2
echo Done
Now, whilst command 2 is running, hitting Ctrl C will cause both command1 and command2 to be sent SIGINT.
Newer versions of GNU Parallel will do what you want:
parallel ::: "command 1" "command 2"
echo "done"
Or if command
remains the same:
parallel command ::: 1 2
echo done
Watch the intro video for a quick introduction: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Walk through the tutorial (man parallel_tutorial). You command line with love you for it.