Search code examples
linuxbashshellbackground-process

Bash run a group of two children in the background and kill them later


Let's group two commands (cd and bash ..) together like this:

#!/bin/bash

C="directory"
SH="bash process.sh"

(cd ${C}; ${SH})&
PID=$!
sleep 1
KILL=`kill ${PID}`

process.sh prints out the date (each second and five times):

C=0
while true
do
    date
    sleep 1
    if [ ${C} -eq 4 ]; then
        break
    fi
    C=$((C+1))
done

Now I actually would expect the background subprocess to be killed right after 1 second, but it just continues like nothing happens. INB4: "Why don't you just bash directory/process.sh" No, this cd is just an example. What am I doing wrong?


Solution

  • Use exec when you want a process to replace itself in-place, rather than creating a new subprocess with its own PID.

    That is to say, this code can create two subprocesses, storing the PID of the first one in $! but then using the second one to execute process.sh:

    # store the subshell that runs cd in $!; not necessarily the shell that runs process.sh
    # ...as the shell that runs cd is allowed to fork off a child and run process.sh there.
    (cd "$dir" && bash process.sh) & pid=$!
    

    ...whereas this code creates only one subprocess, because it uses exec to make the first process replace itself with the second:

    # explicitly replace the shell that runs cd with the one that runs process.sh
    # so $! is guaranteed to have the right thing
    (cd "$dir" && exec bash process.sh) &