views:

35

answers:

2

I've searched for a while but i can't either find an answer or come up with a solution of my own, so I turn to you guys. First question I actually ask here :)

I would like to run several instances of the same program, and redirect each of these programs' standard output to a file that contains that same process' pid, something like:

my_program > <pid of the instance of my_program that is called in this command>.log

I'm aware that this is not even close of the way to go :P I have tinkered around with exec and $PPID but to no avail. My bash-fu is weak :| please help me, point me somewhere! Thanks!

+1  A: 

The problem here is that each new process started by bash gets new PID and you have to redirect the output of that process before starting it. But you cannot tell what PID will be assigned to that process by OS.

The solution to this problem is not to start a new process, but replace the existing bash process with a new one using exec.

Here is an example. First, we write a basic C program that prints its PID:

// printpid.c

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    printf ("C process pid is %d\n", getpid());
    return 0;
}

Then we write a simple bash script that will print its PID and replace itself with this program using exec:

#!/bin/bash
# printpid.sh

echo Bash process PID is $$
exec ./printpid > $$.log

Now, let's write a script that will call this printpid.sh script multiple times:

#!/bin/bash
# example.sh

./printpid.sh
./printpid.sh
./printpid.sh

Now, let's make sure it works:

$ ls
example.sh  printpid  printpid.c  printpid.sh
$ ./example.sh 
Bash process PID is 6397
Bash process PID is 6398
Bash process PID is 6399
$ ls
6397.log  6398.log  6399.log  example.sh  printpid  printpid.c  printpid.sh
$ cat 6397.log 
C process pid is 6397
$ cat 6398.log 
C process pid is 6398
$ cat 6399.log 
C process pid is 6399
$ 

Be aware that when you are using exec you cannot put anything else after that in the script as bash shell replaces itself with a new process specified as command line arguments for exec.

Good luck hacking!

Vlad Lazarenko
+2  A: 

If you have bash 3 or newer, you could combine subshells, exec and ${BASHPID}

That is, create a subshell with ( ), then set up redirection to <pid of subshell>.log and exec my_program, which should replace the process-image of the subshell, inheriting it's pid (among other things).

( exec my_program >${BASHPID}.log )

Kjetil Jorgensen