This usually happens if the process tries to read from its stdin
stream. When the process is in the background, it receives a TTIN signal and is thus frozen (same behavior as a STOP signal). There is also the dual signal TTOU when a background process tries to write to its terminal.
Bringing it to the foreground resumes the process and allows it to read from your terminal.
Demo:
$ cat t.sh
#! /bin/sh
sleep 1
read dummy
$ ./t.sh &
[1] 3364
$
[1]+ Stopped ./t.sh
$ ps aux|grep t.sh
me 3364 0.0 0.0 11268 1200 pts/0 T 17:04 0:00 /bin/sh ./t.sh
One of the ways of avoiding this is to use nohup
, but this can have strange effects if the program doesn't deal with having its input stream redirected to /dev/null
.
As others have said, there isn't any way to wait on "not" a process ID. However this pattern of code doesn't seem that bad to me, so I offer it as a suggested way of achieving what you're after.
It makes use of Bash arrays which you can then give as a list to the wait
command.
Example
A modified version of your example code, cmd.bash
.
!/bin/bash
array[0]=1
array[0]=2
sleep 30 &
pid=$!
pidArr=()
for i in ${array[@]}; do
for n in $(seq 3); do
if [ $n -eq 1 ]; then
sleep 31 > file &
pidArr+=($!)
else
sleep 32 >> file &
pidArr+=($!)
fi
done
done
echo ${pidArr[@]}
I've substituted sleep
commands in this example just to simulate some long running jobs that we can background. They have nothing to do with this other than to act as stand-ins.
Also the final echo
command is there purely so we can see what happens when the for loops complete. Ultimately we'll replace it with an actual wait
command, but let's not get ahead of ourselves.
Example run #1
So let's run our program and see what happens.
$ ./cmd.bash
24666 24667 24668
Now if we check ps
:
$ ps -eaf|grep sleep
saml 24664 1 0 22:28 pts/9 00:00:00 sleep 30
saml 24666 1 0 22:28 pts/9 00:00:00 sleep 31
saml 24667 1 0 22:28 pts/9 00:00:00 sleep 32
saml 24668 1 0 22:28 pts/9 00:00:00 sleep 32
If we wait a bit, these will ultimately finish. But this shows that if we add the process IDs to an array we can echo
them out afterwards.
Example #2
So let's change that echo
line out and swap in a wait
line now, something like this:
wait ${pidArr[@]}
Now when we run our modified version we see that it's waiting on ALL the process IDs:
$ ./cmd.bash
...after ~30 seconds passes
$
We get back our prompt. So we successfully waited for all the processes. A quick check of ps
:
$ ps -eaf|grep sleep
$
So it worked.
Best Answer
Unless I'm misunderstanding your question, it can simply be achieved with this short script:
(and add an extra
wait
at the end if you want your script to wait forprocess_a
to finish before exiting).You can even do this as an one-liner, without the need for a script (as suggested by @BaardKopperud):