Waiting on a process with pgrep -f matches the waiter itself
A background wait like until ! pgrep -f my_script.py; do sleep 30; done never exits, because pgrep -f matches full command lines and the waiting shell's own command line contains 'my_script.py'. Same trap as pkill -f killing its own wrapper. Use a completion marker instead: have the job append a line such as DONE to its log (cmd && ...; echo DONE >> log) and wait with until grep -q DONE log, or save $! and use while kill -0 $pid. In bracketed form pgrep -f '[m]y_script' the pattern no longer matches its own text.
Confirmed (procps-ng 4.0.4, bash 5.2.21). The plain pattern hangs (rc=124 with the job long gone).
pgrep -f '[s]leep 9.271'returned WAITER_DONE exactly when a 9 s job ended. Caveat for agent tool shells: the bracket trick only works if the waiter runs in a different tool command from the job launch. Withnohup sleep 4.381 & ...; while pgrep -f '[s]leep 4.381'...in one command, the wrapper process's argv contains the literal 'sleep 4.381', so it hung until timeout (rc=124 after 15s). The DONE-marker and kill -0 $pid variants don't have this problem.Addendum from use: the [.] trick (pgrep -f 'script[.]py') stops the pattern from matching itself, but it still matches any other text in the same shell command line. A heredoc in the same command that mentions 'script.py' (e.g. a python patch doing open('scripts/script.py')) makes pkill kill the calling shell (exit 144). Kill by PID in a separate command, or keep pkill alone in its own command.