104

I want to run a few commands, each of which doesn't quit until Ctrl+C is pressed. Is there something I can run to run all of them at once, and Ctrl+C will quit them all? They can share the terminal output.

Specifically, I have the compass compiler, coffeescript compiler, and a custom command that watches for file changes all running watching for file changes. I don't want to load up a terminal for each command.

0

7 Answers 7

154

This bash script is for N parallel threads. Each argument is a command.

trap will kill all subprocesses when SIGINT is catched.
wait $PID_LIST is waiting each process to complete. When all processes have completed, the program exits.

#!/bin/bash

for cmd in "$@"; do {
  echo "Process \"$cmd\" started";
  $cmd & pid=$!
  PID_LIST+=" $pid";
} done

trap "kill $PID_LIST" SIGINT

echo "Parallel processes have started";

wait $PID_LIST

echo
echo "All processes have completed";

Save this script as parallel_commands and make it executable.
This is how to use this script:

parallel_commands "cmd arg0 arg1 arg2" "other_cmd arg0 arg2 arg3"

Example:

parallel_commands "sleep 1" "sleep 2" "sleep 3" "sleep 4"

Start 4 parallel sleep and waits until "sleep 4" finishes.

Sign up to request clarification or add additional context in comments.

10 Comments

Very cool. Trap is what I was looking for. I edited your answer to include wait, which will suppress unnecessary "process x exited" messages.
@MTsoul, wait is better than while loop. I've improved my script with your suggestion. It also works for N parallel commands now.
What about running each cmd on a single distinct core? Should I run like: ./parallel_commands "taskset -c 0 cmd arg0 arg1 arg2" "taskset -c 1 other_cmd arg0 arg2 arg3" or taskset -c 2 ./parallel_commands "taskset -c 0 cmd arg0 arg1 arg2" "taskset -c 1 other_cmd arg0 arg2 arg3"
So great. Now i have some commands which are in bash scrip and i want to run them parallel?
Do you want STDOUT or the exit value?
|
122

Based on comment of @alessandro-pezzato. Run multiples commands by using & between the commands.

Example:

$ sleep 3 & sleep 5 & sleep 2 &

It's will execute the commands in background.

5 Comments

Hi @OleTange, I don't know the difference. I tried &! and & and both worked equally.
Thanks for your advice. I change the code and remove the exclamation mark.
Control-C doesn't fully end all parallel commands when execute like this, they will keep running in the background. What's the correct way to end the execution of all the commands?
Run fg and then press Ctrl+C, repeat as needed
this runs them in sequence for me
41

Use GNU Parallel:

(echo command1; echo command2) | parallel
parallel ::: command1 command2

To kill:

parallel ::: command1 command2 &
PID=$!
kill -TERM $PID
kill -TERM $PID

Reference to gnu.org site.

6 Comments

@Oatman: It should be, but GNU parallel is not in all distributions. For example, RHEL 7 doesn't appear to have a package readily available.
Is it possible to track the PID of the parallel process that starts multiple processes and terminate them all by terminating parent parallel?
@StefanMajewsky: parallel is in the EPEL repository.
The citation warning/noise is really annoying! It pollutes the output, you can silence it yes, but why the hell should one do this? Imagine the chaos if all open source tools would have done this!
|
5

It can be done with simple Makefile:

sleep%:
        sleep $(subst sleep,,$@)
        @echo $@ done.

Use -j option.

$ make -j sleep3 sleep2 sleep1
sleep 3
sleep 2
sleep 1
sleep1 done.
sleep2 done.
sleep3 done.

Without -j option it executes in serial.

$ make -j sleep3 sleep2 sleep1
sleep 3
sleep3 done.
sleep 2
sleep2 done.
sleep 1
sleep1 done.

You can also do dry run with `-n' option.

$ make -j -n sleep3 sleep2 sleep1
sleep 3
sleep 2
sleep 1

Comments

1

I am suggesting a much simpler utility I just wrote. It's currently called par, but will be renamed soon to either parl or pll, haven't decided yet.

https://github.com/k-bx/par

API is as simple as:

par "script1.sh" "script2.sh" "script3.sh"

Prefixing commands can be done via:

par "PARPREFIX=[script1] script1.sh" "script2.sh" "script3.sh"

2 Comments

After trying and failing to do what you describe above using gnu parallel I succeeded on the first try using your utility. Nice work!
The first: parallel ::: "script1.sh" "script2.sh" "script3.sh" The second would normally use --tag: parallel --tag ::: "script1.sh" "script2.sh" "script3.sh"
0

You may use multitail utility

multitail -l "command1" -l "command2"

It spits screen and show output in different views

Comments

-15

To run multiple commands just add && between two commands like this: command1 && command2

And if you want to run them in two different terminals then you do it like this:

gnome-terminal -e "command1" && gnome-terminal -e "command2"

This will open 2 terminals with command1 and command2 executing in them.

Hope this helps you.

2 Comments

This is incorrect. It runs command2 after command1 and only if command1 succeeds. Try sleep 3 && sleep 3 and you will see it takes 6s.
command1 && command2 doesn't start executing at once. it will be executed one after another (considering success scenario for command).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.