Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a script that I would like to fork at one point so two copies of the same script are running.

For example, I would like the following bash script to exist:

echo $$
do_fork()
echo $$

If this bash script truly existed, the expected output would be:

<ProcessA PID>
<ProcessB PID>
<ProcessA PID>

or

<ProcessA PID>
<ProcessA PID>
<ProcessB PID>

Is there something that I can put in place of "do_fork()" to get this kind of output, or to cause the bash script to do a C-like fork?

share|improve this question
add comment

3 Answers 3

up vote 7 down vote accepted

Yes. Forking is spelled &:

echo child & echo parent

What may be confusing you is that $$ is not the PID of the shell process, it's the PID of the original shell process. The point of making it this way is that $$ is a unique identifier for a particular instance of the shell script: it doesn't change during the script's execution, and it's different from $$ in any other concurrently running script. One way to get the shell process's actual PID is sh -c 'echo $PPID'.

The control flow in the shell isn't the same as C. If in C you'd write

first(); fork(); second(); third();

then a shell equivalent is

after_fork () { second; third; }
first; after_fork & after_fork

The simple shell form first; parent & child corresponds to the usual C idiom

first(); if (fork()) parent(); else child();

& and $$ exist and behave this way in every Bourne-style shell and in (t)csh. $PPID didn't exist in the orignal Bourne shell but is in POSIX (so it's in ash, bash, ksh, zsh, …).

share|improve this answer
1  
But that's basically "fork + exec", not just fork. –  mattdm Feb 18 '11 at 0:41
    
@mattdm: Uh? & is fork, there's no exec involved. Fork+exec is when you launch an external command. –  Gilles Feb 18 '11 at 0:47
    
@mattdm: Ah, I think I see what Cory is getting at. There's no exec, but the two languages do have different control flow. –  Gilles Feb 18 '11 at 0:55
    
@Gilles: The bash control operator & starts a subshell in which the given command is executed. Fork + exec. You can't just put & with no preceding command to execute. –  mattdm Feb 18 '11 at 0:58
    
@mattdm: Yes, the control flow is different, but exec doesn't come into play. See it with truss/trace/dtrace/strace if you don't believe me! –  Gilles Feb 18 '11 at 1:01
show 4 more comments

There's no native bash (or, to my knowledge, any other typical *nix shell) way of doing this. There's a lot of ways to spawn forked processes that do something else asynchronously, but I don't think there's anything that follows the exact semantics of the fork() system call.

The typical approach would be to have your top-level script spawn off helpers that do just the work you want split out. If you do $0 $@ & or whatever, you'll start at the beginning again and need to figure that out somehow.

I'm actually starting to think of several clever ways in which one might do just that....

But, before my brain gets too carried away with that, I think a pretty good rule is: if you're trying to write something in shell and it's getting full of clever tricks and you're wishing for more language features, time to switch to a real programming language.

share|improve this answer
add comment

Yes, it's called subshells. Shell code inside parenthesis is run as a subshell (fork). However the first shell normally waits for the child to complete. You can make it asynchronous using the & terminator. See it in in action with something like this:

#!/bin/bash

(sleep 2; echo "subsh 1")&
echo "topsh"

$ bash subsh.sh

share|improve this answer
3  
The parentheses create a subshell, but that's fork+wait. & is fork alone. If you want to execute more than one pipeline in the child process, it's enough to use braces (which perform grouping without creating a child process): { sleep 2; echo child; } & –  Gilles Feb 18 '11 at 8:31
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.