Analysis
;is a command terminator that makes the shell run the command synchronously.&is a command terminator that makes the shell run the command asynchronously.
&; in your augmented code is two terminators where the shell expects exactly one. To terminate a command use either & or ;, not both.
Do not try to use & where you tried to use it. Using & instead of &; would make the shell code syntactically valid, yet wrong for reasons stated below. & here makes no sense, because while whatever & do :; done would make the shell interpreting the script run whatever asynchronously and then:
The exit status of
whateverwould not matter because the shell would not wait for it. The exit status of a command is known after the command exits. Having just runwhatever &, the shell proceeds past&when the exit status ofwhateverstill belongs to the future.* Normally starting a command asynchronously is a success (seefalse & echo "$?").* It may happen
whateveris scheduled early and exits before the shell is scheduled to continue, still the shell cannot count on this. It doesn't even try and reports a success. Not relying on a race condition is a good thing.As the shell would not wait for
whateverto exit and it would see success fromwhatever &, it would proceed to:and loop again and again. In effect it would keep spawningwhatevers. Then:It may happen
whatevers exit fast enough to balance the inflow of newwhatevers from the loop. The script will never exit by itself, its parent will forever wait for it to exit.Or
whatevers will accumulate until some resource (e.g. memory or number of processes) is depleted. When some resource is depleted,whatever &will fail and the loop will end, so the script will proceed toecho. Note that other processes may suffer first, including the shell interpreting the script (so it may be killed before it gets toecho) and the parent of the script (so instead of unblocking the startup you may get it killed).In the best (or rather "least bad") scenario the parent survives, the script exits or gets killed and the parent continues. Even then few ((hundreds of) thousands of)
whatevers may survive. This will be especially likely ifwhateveris designed to be a long-running process.
None of these is what you want.
Solutions
(Note: each numbered point is an independent solution; choose one that fits you most; there should never be a need for mixing them.)
If you can, make the parent run your original script asynchronously. If the parent is itself a shell interpreting some script then the syntax in that script will be:
/path/to/original/script &E.g. the above should work in
rc.local(if your OS uses this file) or in your~/.bashrc.Make your original script run its entire body asynchronously. The idea is to make the script exit and leave an asynchronous child shell behind. This should unblock the parent, even if the parent invoked the script synchronously.
This is your original script modified to implement the idea:
#!/bin/bash(while sudo /home/pi/MyCode; do :; doneecho Error with MyCode) &
In solutions using &, depending on how you want your script to behave, you may need additional steps. For a start read What's the difference between running a program as a daemon and forking it into background with &? to see what I mean. To just unblock the parent a proper use of & should be enough though.
If your OS uses systemd then consider creating a service. The relevant fragment of the
.servicefile will be:[Service]Type=execExecStart=/path/to/original/scriptIn a system service you don't need
sudo. And if/home/pi/MyCodeis designed to only occasionally exit (with success) then considerExecStart=/home/pi/MyCodewithRestart=on-success, so you won't need the script implementing the loop at all.If you decide to create a system service (rather than user service) then consider moving
MyCodeto a directory owned by root.