Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

(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 
like image 291
Betty Crokker Avatar asked Dec 02 '13 21:12

Betty Crokker


People also ask

Can a child process create another child process?

Yes. The process creates a child, which then creates another child, becoming it's parent. You can differentiate child and parent by using fork return number.

How do you know if a process is a child?

A process can only have a single parent process, which is always obtainable by calling getppid . The child is a copy of the parent, it gets a copy of the parent's data space, heap and stack. They do not share these portions of memory!

Can child process exist without parent process?

A child process may also be known as subprocess or a subtask. A child process is created as a copy of its parent process. The child process inherits most of its attributes. If a child process has no parent process, then the child process is created directly by the kernel.

When new process created the address space of child process will be?

Also, Linux uses copy on write when creating child processes. This means that the parent and child will share the parent address space until one of them does a write, at which point the memory will be physically copied to the child. This eliminates unneeded copies when exec ing a new process.


2 Answers

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.

like image 152
that other guy Avatar answered Oct 11 '22 22:10

that other guy


Another way is to abandon the child

#!/bin/bash  yourprocess &  disown 

As far as I understand, the application replaces the normal bash shell because it is still waiting for a process to finish even if init should have taken care of this child process. It could be that the "application" intercepts the orphan handling which is normally done by init.

In that case, only a parallel process with some IPC can offer a solution (see my other answer)

like image 40
thom Avatar answered Oct 11 '22 21:10

thom