Shell scripting trying to launch tasks in parallel? - linux

The basic task I need to do is call a python script multiple times, each time with a different argument. For example:
script.py -t command1
script.py -t command2
script.py -t command3
Etc. Now the problem is that script.py takes a long time to run, so just putting the above in a shell script and running them in series (one after another) is a waste of time.
Instead what I'd like to be able to do is open up multiple terminals, and in each one, run
script.py -t command_i
For the ith command argument. Is there any way of doing this? If not, are there any other helpful parallel options for what I'm trying to do?
Cheers
EDIT - just realized: I probably want some sort of forking, yes? I've never done that with shell scripting though.

To run a command in the background, add an & at the end:
script.py -t command1 &
script.py -t command2 &
script.py -t command3 &
If you are using this in a shell script and want to wait for all the processes to finish, run wait without arguments. It will wait for all background jobs in the current shell to complete before continuing the script.

Related

Bash function to automatically run a command in background and disown

I'm trying to make a function in my bashrc that would allow me to launch any command and automatically disown it.
e.g. launch ./myprogram or launch xdg-open myfolder
I've been used to do that many times command ; Ctrl+Z ; bg ; disown and would like to simply create a shortcut of these steps.
However I don't know how to embed the action of Ctrl+Z in a bash script. I've seen that its action is SIGTSTP, but I'm really lost as to how incorporate that in a bash function.
You can run the command in background directly instead of stopping it and then running it in the background. Use the &:
$ cat > launch
#! /bin/bash
"$#" & disown
Ctrl + d
$ chmod u+x ./launch
For posterity and othe people passing by, here is the bash function I made :
launch()
{
"$#" > /dev/null 2>&1 & disown
}
"$#" takes every arguments given in the prompt as one
> /dev/null 2>&1 redirects every output (stout and stderr) to dev/null which effectively delete them automatically, so that it doesn't appear on the shell
& runs the command in background, meaning it will let you input other commands in the shell
disown , as the name implies will lake it so that the process is no longer bound to the shell and you cans safely close the shell without it closing the process at the same time.

Does '&' perform parallel or linear jobs in linux shell scripting?

I was trying to search online but didn't get a definite answer for this. Does the symbol & in linux perform two jobs in parallel or in a linear way?
for example:
command1 & command2
Here, will command1 and command2 be performed in parallel or will command2 be performed AFTER command1 finishes? What is exactly happening here?
The reason I'm asking this is because in my command1 and command2 I am calling scripts with different arguments which write some data to the same text file. After running the aforementioned script, I see that the output of command2 is being appended to command1. Is this the expected behaviour if they are truly working in parallel?
Try this on for size:
$ ls & pwd
[1] 7592 <---"ls" being put in the background as job #1, with pid 7592
/home/marc <--- output of "pwd"
$ stuff
^---------------- shell waiting for next input
^^^^^---------- output of "ls" command
a & b places the a program in the background, and immediately starts executing the b command as well. It's not exactly parallel, but it is two completely separate processes that happen to be sharing a common output: your terminal

Start subscript in bash script in background so that it still runs when I close the terminal/ssh session

I am trying to write a simple bash script that should start an other script as another user and in a way that the script
Still runs, when i close the main script
Still runs, when I close the terminal or the ssh session
can be stopped by a simple call of another script.
What I have right now:
This is basically how start.sh looks like
# doing some other stuff
sudo su user_the_script_should_start_as -c "./start-in-background.sh $1 $2 $3"
start-in-background-sh
# doing some other stuff
# Start other Script in Background
How can I do those three points?
You can use
nohup bash your_script.sh &
or
disown bash your_script.sh &
or
screen
But my suggestion is screen command. Also tumx is good to use.
And for your last requirement to stop script on call will be able to achieved by following command,
kill $!

Unable to execute a bash script in background from another bash script

I have a shell script which I want to invoke in background, from another shell script. Both the scripts are bash scripts.
First script(a.sh) is something like:
read a
echo 'something'
read b
echo 'something else'
# some if else conditions
nohup bash b.sh 2>&1 > /tmp/log &
When I try to execute the above script as: ./a.sh arg1 arg2 | tee log
, very strangely it stucks at the nohup line for the second script b.sh to finish whereas it should not.
But when I just have the following line in the script, it works as expected:
nohup bash b.sh 2>&1 > /tmp/log &
Please help. I can also share the exact scripts if required.
This is what you wanted to happen:
The script runs and output things
The script runs a command in the background
The script exits
The pipe closes
tee exits
This is what's happening:
The script runs and outputs things
The script runs a command in the background, with the pipe as stderr
The script exits
The pipe is still held open by the backgrounded command
tee never exits.
You fixed it by pointing stderr to the log file rather than the pipe, so that the backgrounded process no longer keeps the pipe open.
The meaning of the order of 2>&1 and the redirect has been explained in other answers, and shellcheck would have automatically pointed out this problem in your code.

What is the difference between & and | in linux?

I understand | pipes the output of the first command into the stdin of the second command. How does & relate two processes?
Probably you want to know about && not & (which is for executing a command in background)
This command:
command1 | command2
Means pass output of command1 as input (stdin) of command2
But in this command:
command1 && command2
Means execute command2 ONLY if command1 is successful
Single amperstand (&) is used for backgrounding. It makes the command run in the background.
Also from man bash :
If a command is terminated by the control operator &, the shell
executes the command in the background in a subshell. The shell does
not wait for the command to finish, and the return status is 0.
So if you write something like this:
find -name hello &
This will make the find command to be forked and run in the background
In your case single amperstand & does not relate to the two process in any way.
You are probably looking for
command1 && command2
& does not relate two processes in any way; it starts a process in the "background" so that the shell you are running continues its work without waiting for the process to terminate like it normally would.
You are probably thinking of &&. The command line
command 1 && command 2
executes first command 1, and if it is successful (exits with status code 0) it executes command 2. The exit status of the compound is the exit status of the first command if unsuccessful, otherwise the exit status of 2.
For example, the following command line can be used to install Unix software from source, but only if it is successfully configured, compiled, and all tests run.
./configure && make && make test && make install

Resources