Reputation: 6242
Let assume I have multiple files paths for run from terminal, I want them to be run on parallel in the background without printing their output to the console screen. (Their output should be saved to some other log path which is defined in the python file itself).
The paths are in this format:
/home/Dan/workers/1/run.py
/home/Dan/workers/2/run.py etc.
When I try to do something like running one worker in background it seems to work:
In example: cd /home/Dan/workers/1/
and python run.py > /dev/null 2>&1 &
And ps -ef |grep python
, indeed show the script running on background without printing to console, but printing to its predefined log path.
However, when I try to launch them all via bash script, I've no python scripts run after the following code:
#!/bin/bash
for path in /home/Dan/workers/*
do
if [-f path/run.py ]
then
python run.py > /dev/null 2>&1 &
fi
done
Any idea what is the difference? In bash script I try to launch many scripts one after another just like I did for only one script.
Upvotes: 2
Views: 943
Reputation: 990
What I would suggest is, not to invoke via loop. Your path suggests that you will be having multiple scripts. Actually the loop statement which you have included invokes each python script sequentially. It will run second one only when first one is over.
Better add
#!/bin/python
on the top in your python scripts (or whichever path your python is installed)
and then run
/home/Dan/workers/1/run.py && /home/Dan/workers/2/run.py > /dev/null 2>&1 &
Upvotes: 0
Reputation: 140786
#!/bin/bash
There is nothing bash-specific about this script; write #! /bin/sh
instead. (Don't write bash-specific scripts, ever; if a bash-specific feature appears to be the easiest way to solve a problem, that is your cue to rewrite the entire thing in a better programming language instead.)
for path in /home/Dan/workers/*
do
This bit is correct.
if [-f path/run.py ]
... but this is wrong. Shell variables are not like variables in Python. To use (the jargon term is "expand") a shell variable you have to put a $
in front of it. Also, you need to put double quotation marks around the entire "word" containing the shell variable to be expanded, or "word splitting" will happen, which you don't want. (There are cases where you want word splitting, and then you leave the double quotes out, but only do that when you know you want word splitting.) Also also, there needs to be a space between [
and -f
. Putting it all together, this line should read
if [ -f "$path/run.py" ]
.
then
python run.py > /dev/null 2>&1 &
fi
The run.py
on this line should also read "$path/run.py"
. It is possible, depending on what each python script does, that you instead want the entire line to read
( cd "$path" && exec python run.py > /dev/null 2>&1 ) &
I can't say for sure without knowing what the scripts do.
done
There should probably be another line after this reading just
wait
so that the outer script does not terminate until all the workers are done.
Upvotes: 2
Reputation: 17051
#!/bin/bash
for path in /home/Dan/workers/*
do # VV V-added ${}
if [ -f "${path}/run.py" ]
then
python "${path}/run.py" > /dev/null 2>&1 &
# or (cd $path; python run.py > /dev/null 2>&1 &) like Terje said
fi
done
wait
Use ${path}
instead of just path
. path
is the name of the variable, but what you want when you are testing the file is the value that is stored in path
. To get that, prefix with $
. Note that $path
will also work in most situations, but if you use ${path}
you will be more clear about exactly which variable you mean. Especially when learning bash, I recommend sticking with the ${...}
form.
Edit: Put the whole name in double-quotes in case ${path}
contains any spaces.
Upvotes: 3
Reputation: 6315
One important difference is that your bash script does not cd into the subdirectories before calling run.py
The second last line should be
python ${path}/run.py > /dev/null 2>&1 &
or
(cd $path; python run.py > /dev/null 2>&1 &)
Upvotes: 1