What commands would I use to create two child processes serially?
Solution 1:
You can use the xargs
utility for this. It can run a command for each line on stdin, so we just need to ensure that xargs
gets as input a single line on stdin at the time it should start the command, which can be accomplished with grep
:
proc1 | grep --max-count=1 "${targetString}" | xargs --max-lines=1 --no-run-if-empty --replace -- proc2
The arguments --max-count=1
, --max-lines=1
and --no-run-if-empty
ensure that proc2
is started exactly once if and when proc1
outputs ${targetString}
for the first time, and never if proc1
never outputs ${targetString}
.
The --replace
avoids that xargs
appends the input line to its command line.
I used the following command line to test it:
(echo Start >&2; sleep 3 ; echo Trigger; sleep 3; echo End >&2) | grep --max-count=1 Trigger | xargs --max-lines=1 --no-run-if-empty --replace -- echo "Triggered"
Solution 2:
I'm not sure there is an elegant command / answer to the question you asked (i.e. reach a certain point in its execution) - but there are tools / techniques which can be used to bodge up a solution, probably involving more than 1 of the following, and maybe other things I don't know about yet:
- Backgrounding processes (&)
- Conditional execution (&& and ||)
- sleep
- wait (I expect this will be particularly useful - if you launch more than 1 job in the background, it will wait until all the jobs are completed)
- Named pipes (which could provide a mechanism to talk between processes).
- inodenotifywait
Writing and checking lock files is also common practice (pro tip - if you have control of the environment, write to the ramdisk rather than /tmp - on many distros this is /dev/shm).
Solution 3:
This is just an idea, but have the first process pipe its output to grep. Have grep pipe its output to a read line loop, and compare each line with what you're looking for. Once found, execute proc2.
#!/bin/bash
targetString="line you are looking for"
proc1 | grep "${targetString}" |
while read line
do
if [ "$line" = "${targetString}" ]; then
proc2
fi
done
If "a certain point in its execution" can be determined by stdout
, then how about the following?
proc1 | grep "stdout trigger string" && proc2
&&
should fire when grep
returns 0
, which it only does when it finds a match.