Home » Linux » How to set process group of a shell script

How to set process group of a shell script

Posted by: admin November 30, 2017 Leave a comment

Questions:

How to set process group of a shell script ? Also I want all the child process to be in the same process group

I expect something similar to setpgid() in C.

Answers:

As PSkocik points out, it is possible to run a process in its own process group, in most shells, by activating job control (“monitor mode”).

(set -m; exec process_in_its_own_group)

Linux has a setsid utility, which runs the command passed as argument in its own session (using the eponymous system call). This is stronger than running it in its own process group à la setpgrp, but that may be ok for your purpose.

If you want to place the process in an existing group rather than in its own group (i.e. if you want the full power of setpgid), there’s no common shell utility. You have to use C/Perl/…

Questions:
Answers:

I don’t think Bourne, bash, or zsh will let you do that, but you could do it in perl using the built-in setpgrp (note the slight name difference from POSIX). Pass zero as the PID to modify the group of the perl process itself:

setpgrp(0, 12345) || die "$!"

You might think you could use perl from, say, bash to set the bash process’s group (by passing $$ to a perl script, for example), but I don’t think the perl process would be able to modify the group of a process that it didn’t fork.

Depending on what you’re trying to do, the job control features in various shells may give you what you need, in a different way, like if you just want to detach from the terminal.

UPDATE: I think it’s strange that this answer has received a couple of down-votes without clear explanation why. My guess is that the downvoters are misunderstanding the question, which is asking how to change the process group of the current shell. Or perhaps they know how to do a setpgrp from the shell but are keeping the secret to themselves.

Questions:
Answers:

I’ll answer part of what I understand:

How to force current bash shell script to be it self process group:

I put this in the beginning of my bash script:

pgid_from_pid() {
    local pid=$1
    ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+"
}

pid="$$"
if [ "$pid" != "$(pgid_from_pid $pid)" ]; then
    exec setsid "$(readlink -f "$0")" "[email protected]"
fi

Why do I would need this ?

When launching a program from an interactive bash session, it gets its own new process group. But this is not the case if your program is called from a bash script (non-interactive). If your program relies on being the process group owner in both condition you’ll need this.

Questions:
Answers:

If you turn set -m on, new processes will be spawned in a new process group, and if they’re backgrounded, they won’t have SIGINT and SIGQUIT ignored.

if  [ $$ = $(ps -o pgid -hp $$) ]; then
   echo already a process group leader;
else
   set -m
   $0 "[email protected]" #optionally with &
   set +m
fi

The new processes group of programs run after set -m takes over as the foreground process group of the terminal, unless they’re run in the background.

The set -m is apparently semi-standard, required by POSIX if the implementation supports “User Portability Utilities”.
In practice it works on bash, dash, ksh, pdksh, sh, yash, and zsh. posh doesn’t have it.

Questions:
Answers:

As @Rob Davis pointed out in his answer, setting process group is not what you want for shells.

Instead you want to use their process control mechanisms. This answer covers doing this for sh on linux and borne. In short:

#! /bin/sh
# Kill all opened jobs on exit.
trap 'kill $(jobs -p)' EXIT

This will kill any jobs opened in the backrground (e.g. with &).