How can I launch a new process that is NOT a child of the original process?

Betty Crokker picture Betty Crokker · Dec 2, 2013 · Viewed 34.2k times · Source

(OSX 10.7) An application we use let us assign scripts to be called when certain activities occur within the application. I have assigned a bash script and it's being called, the problem is that what I need to do is to execute a few commands, wait 30 seconds, and then execute some more commands. If I have my bash script do a "sleep 30" the entire application freezes for that 30 seconds while waiting for my script to finish.

I tried putting the 30 second wait (and the second set of commands) into a separate script and calling "./secondScript &" but the application still sits there for 30 seconds doing nothing. I assume the application is waiting for the script and all child processes to terminate.

I've tried these variations for calling the second script from within the main script, they all have the same problem:

  • nohup ./secondScript &
  • ( ( ./secondScript & ) & )
  • ( ./secondScript & )
  • nohup script -q /dev/null secondScript &

I do not have the ability to change the application and tell it to launch my script and not wait for it to complete.

How can I launch a process (I would prefer the process to be in a scripting language) such that the new process is not a child of the current process?

Thanks, Chris

p.s. I tried the "disown" command and it didn't help either. My main script looks like this:

[initial commands]
echo Launching second script
./secondScript &
echo Looking for jobs
jobs
echo Sleeping for 1 second
sleep 1
echo Calling disown
disown
echo Looking again for jobs
jobs
echo Main script complete

and what I get for output is this:

Launching second script
Looking for jobs
[1]+ Running ./secondScript &
Sleeping for 1 second
Calling disown
Looking again for jobs
Main script complete

and at this point the calling application sits there for 45 seconds, waiting for secondScript to finish.

p.p.s

If, at the top of the main script, I execute "ps" the only thing it returns is the process ID of the interactive bash session I have open in a separate terminal window.

The value of $SHELL is /bin/bash

If I execute "ps -p $$" it correctly tells me

PID   TTY TIME    CMD
26884 ??  0:00.00 mainScript

If I execute "lsof -p $$" it gives me all kinds of results (I didn't paste all the columns here assuming they aren't relevant):

FD   TYPE   NAME
cwd  DIR    /private/tmp/blahblahblah
txt  REG    /bin/bash
txt  REG    /usr/lib/dyld
txt  REG    /private/var/db/dyld/dyld_shared_cache_x86_64
0    PIPE   
1    PIPE   -> 0xffff8041ea2d10
2    PIPE   -> 0xffff 8017d21cb
3r   DIR    /private/tmp/blahblah
4r   REG    /Volumes/DATA/blahblah
255r REG    /Volumes/DATA/blahblah

Answer

that other guy picture that other guy · Dec 2, 2013

The typical way of doing this in Unix is to double fork. In bash, you can do this with

( sleep 30 & )

(..) creates a child process, and & creates a grandchild process. When the child process dies, the grandchild process is inherited by init.


If this doesn't work, then your application is not waiting for child processes.

Other things it may be waiting for include the session and open lock files:

To create a new session, Linux has a setsid. On OS X, you might be able to do it through script, which incidentally also creates a new session:

# Linux:
setsid sleep 30

# OS X:
nohup script -q -c 'sleep 30' /dev/null &

To find a list of inherited file descriptors, you can use lsof -p yourpid, which will output something like:

sleep   22479 user    0u   CHR 136,32      0t0       35 /dev/pts/32
sleep   22479 user    1u   CHR 136,32      0t0       35 /dev/pts/32
sleep   22479 user    2u   CHR 136,32      0t0       35 /dev/pts/32
sleep   22479 user    5w   REG  252,0        0  1048806 /tmp/lockfile

In this case, in addition to the standard FDs 0, 1 and 2, you also have a fd 5 open with a lock file that the parent can be waiting for.

To close fd 5, you can use exec 5>&-. If you think the lock file might be stdin/stdout/stderr themselves, you can use nohup to redirect them to something else.