Unix & Linux Asked by ljs.dev on December 3, 2021
I have been using this command successfully, which changes a variable in a config file and then executes a Python script within a loop:
for((i=114;i<=255;i+=1)); do echo $i > numbers.txt; python DoMyScript.py; done
As each DoMyScript.py
instance takes about 30 seconds to run before terminating, I’d like to relegate them to the background while the next one can be spawned.
I have tried what I am familiar with, by adding in an ampersand as below:
for((i=114;i<=255;i+=1)); do echo $i > numbers.txt; python DoMyScript.py &; done
However, this results in the below error:
-bash: syntax error near unexpected token `;'
As stated by the other answers:
;
after the &
.;
after the &
will result in a command
that will run without shell syntax errors.
However, it is unlikely to function correctly,
because it creates a race condition.The OP stated that he resolved the race condition by adding a 3 second delay.
Nobody mentioned:
for ((i=114;i<=255;i++)); do python DoMyScript.py --number="$i" & done
and do away with the file.for i in {114..125}; do ( subdir="dir.$i" && mkdir "$subdir" && cd "$subdir" &&
echo "$i" > numbers.txt && python ../DoMyScript.py; cd .. && rm -r "$subdir" ) & done
This gives each script process a separate numbers.txt
file,
by giving it a separate directory to run in.
The directory is created and deleted, and the script is run, in a subshell.
If DoMyScript.py
accesses any files other than numbers.txt
by relative pathnames,
the above command will need to be adjusted to accommodate that.
The above was inspired by glenn jackman’s answer (although I believe that mine will work and his won’t).
If command B
depends on the success of command A
,
then A && B
is better defensive programming
than A; B
.
But it’s probably not the ideal way to handle this situation.
If mkdir dir.114
fails, then the next 111 attempts are likely to fail also,
and you’ll get 112 error messages.
It would be better to abort the loop if a fatal error occurs.
The fact that the action is happening in an asynchronous subshell makes this somewhat tricky.
for i in {114..125}; do
{ subdir="dir.$i" && mkdir "$subdir" && echo "$i" > "$subdir"/numbers.txt; } || break;
( cd "$subdir" && python ../DoMyScript.py; cd .. && rm -r "$subdir" ) & done
will cause the loop to abort if a mkdir
or an echo value > file
command fails.
It might be better to work in a directory
that is ‘‘guaranteed’’ to be writable, like /tmp
.
However, this increases the risk that your command
will collide (interfere) with some other process.
$$
to the directory name;
e.g., dir.$$.$i
or even dir.$BASHPID
.mkdir
or the file creation might fail because the filesystem is full.Note that the above code will keep on going and remove the temporary directory even if the script fails. You might want to do something else in that situation.
mkdir "$subdir"
succeeds but the cd "$subdir"
fails,
this will go ahead and do cd .. && rm -r "$subdir"
.
If there is a directory with a name like dir.114
in your parent directory
(i.e., parallel to your current directory), it will be removed.
I believe that you can (at least somewhat) fix this
by changing the last line to
( cd "$subdir" && { python ../DoMyScript.py; cd ..; } && rm -r "$subdir" ) & done
or by using absolute paths; e.g., subdir="$PWD/dir.$i"
.Answered by G-Man Says 'Reinstate Monica' on December 3, 2021
Given Stephane's comment on 1_CR's answer, you probably want:
for i in {114..255}; do { echo $i > numbers.txt && python DoMyScript.py; } & done
Answered by glenn jackman on December 3, 2021
Lose the ;
:
for((i=114;i<=255;i+=1)); do echo $i > numbers.txt;python DoMyScript.py & done
Answered by Martin von Wittich on December 3, 2021
Drop the ;
after &
. This is a syntactic requirement
for((i=114;i<=255;i+=1)); do echo $i > numbers.txt;python DoMyScript.py & done
Answered by iruvar on December 3, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP