At one point, you were close to what you seem to want.
a.sh
#!/bin/sh
echo "a.sh running"
sleep 10s
(sleep 10s; pkill -f b.sh) &
bash b.sh
sleep 10s
pkill -f b.sh
echo "a.sh still running"
b.sh (same as your version)
echo "b is now running"
sleep 1000s
echo "Bananas"
The (sleep 10s; pkill -f b.sh) & line in a.sh
creates a subshell that sleeps for ten seconds and then kills b.sh.
It then puts that subshell into the background,
so a.sh can keep running.
a.sh then runs b.sh, which runs sleep 1000s.
Ten seconds later, the sleep 10s in the subshell finishes,
and it (the subshell) runs pkill -f b.sh, killing the b.sh process.
a.sh then resumes running.
The second pkill -f b.sh does nothing,
since the b.sh process is already terminated.
This is what happens when it runs:
$ ./a.sh
a.sh running # immediately
b is now running # about 10 seconds after the above
./a.sh: line 6: 13684 Terminated bash b.sh # about 10 seconds after the above
a.sh still running # about 10 seconds after the above
$ # immediately after the above
This has the advantage that a.sh can resume running immediately
if b.sh finishes quickly.
Only if b.sh runs for more than 10 seconds does the pkill kick in.
In the other answer, a.sh has to sit idle
while the sleep before the pkill takes up time,
even if b.sh has already wrapped up.
Another user posted a comment (now deleted) saying
I get
./a.sh
a.sh running
b is now running
Terminated
not what you report. Any idea?
It was a dark and stormy night. Suddenly, a shot rang out!
—It Was a Dark and Stormy Night, Snoopy
by Charles M. Schulz
The argument to pgrep and pkill is a regular expression;
specifically, an Extended Regular Expression1.
Try running cat and cut simultaneously2.
Then do pgrep c.t — it will list two PIDs,
and you can confirm with ps that they are cat and cut.
If you had done exactly what I said,
you really should have gotten the same results I did.
But I’m willing to wager 42 Zorkmids that you did something different.
You either:
- Began
a.sh with #!/bin/bash as a she-bang (first line)
instead of #!/bin/sh, or
- Ran
a.sh with bash a.sh instead of ./a.sh.
Suddenly, a shot rang out!
b.sh is a regular expression that matches b
followed by any character followed by sh.
It matches itself (b.sh),
and also things like b!sh, b~sh, b&sh, b7sh, and bush.
And … … (wait for it) … … it also matches bash!
So pkill -f b.sh kills all bash processes,
and also any others that have b.sh in their names.
When I ran what I ran, my login shell
(which is at least partially immune to pkill) was bash,
but a.sh was running under /bin/sh
(but b.sh was running under bash).
The pkill -f b.sh command killed the bash b.sh process
because it contained both bash and b.sh.
But the /bin/sh that was running a.sh was unaffected.
Assuming you ran it the way I believe you ran it
(either of the two alternatives),
all the script processes were running bash.
And so the pkill -f b.sh command killed all the script processes.
Change pkill -f b.sh to pkill -f 'b\.sh'
(escaping the dot so it matches only a dot, and not any character),
and you should get the right results.
________
1 pgrep(1)
2 If you have two terminals (shell windows),
run cat | cut -f1 (with input from the terminal) in one of them,
and the p-commands in the other.
If you have only one terminal,
run sleep 42 | cat | cut -f1 &
(without the sleep, the pipeline would collapse immediately),
and then run p-commands in the same window.