简体   繁体   中英

How to prevent bash subshell from waiting for child process

I have a bash script that among other things, launches a background process. I use a function that setups some configuration for the process, launches it, checks it started correctly, and returns its PID, which is used later to kill the subprocess. The sample code below has the same structure but simplified logic:

function launcher(){
    sleep 30 &
    echo $!


PID=$(launcher)
echo $PID
kill $PID

The issue I'm facing is that the subshell that executes the launcher function does not return until the sleep command ends. Therefore the echo $PID statement is not executed until the subshell ends.

what surprises me is that if I check the sleep command, it does not have the script as parent id:

UID        PID  PPID  C STIME TTY      STAT   TIME CMD
user     20135     1  0 18:39 pts/8    S+     0:00 sleep 30

How can I start the sleep & in the background to allow the subshell to end before it ends?

Note : Please notice in my case, the background process will never end until I kill it, so I need the subshell to end get the PID. Also notice in my real code, the logic of the launcher function is quite complex and I'm running it as a subshell to isolate the main process from it.

Thanks in advance

I'm not sure if this gets it done but

function launcher(){
    echo "start launching"
    sleep 100  &
    echo "end launching"
}

launcher
PID=$!

# Here $PID is the process id of `sleep`
echo $PID
kill $PID

Without the kill , this runs the sleep command forked and the shell script ends leaving the sleep command running with the pid set in PID which means you could kill it later or not.

Is this what you need? If not, can you clarify what you're expecting?

I also noticed that if the parent script stays alive, the PPID of the sleep process is correct and stays in tact.

# sleeper_test.sh
#!/bin/bash
function launcher(){
    echo "start launching"
    sleep 100  &
    echo "end launching"
}

launcher
PID=$!

# Here $PID is the process id of `sleep`
echo $PID

sleep 10
#kill $PID

$ ps -ef | grep sleep
  501 13748  5471   0  1:54PM ttys000    0:00.00 /bin/bash ./sleeper_test.sh
  501 13749 13748   0  1:54PM ttys000    0:00.00 sleep 100 <- child correctly tied to the parent sh script
  501 13750 13748   0  1:54PM ttys000    0:00.00 sleep 10
$ ps -ef | grep sleep
  501 13749     1   0  1:54PM ttys000    0:00.00 sleep 100 <- since the parent ended - it's parent becomes the root process parent
``

It happens that the problem was about stdin because the main shell was reading from the subshell's stdout , which is inherited by the background process. Just redirecting the stdout when invoking the background process makes it work as expected.

sleep 100 > /dev/null &

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM