0

I have a script like so:

sh child1.sh &
child=$!
sh child2.sh
kill "$child"

where I run a background process child1 for the other process: child2 to use, and when child2 is done, I kill child1.

Now for whatever reason, I now want to run child1.sh in a sub-process, namely run it like this:

(sh child1.sh)

how can I pass on the id of the sub-process to the parent so I can kill it as before?

I tried:

(sh child1.sh &)

and

(sh child1.sh ) &

but neither seemed to work.

tripleee
  • 175,061
  • 34
  • 275
  • 318
Maths noob
  • 1,684
  • 20
  • 42
  • hmm I am using `()` for this reason: https://stackoverflow.com/questions/786376/how-do-i-run-a-program-with-a-different-working-directory-from-current-from-lin/786419#786419 I want to avoid having to cd back to the original directory. maybe I am not using the right terminology? – Maths noob May 19 '21 at 11:03
  • 2
    I would say that the way to do it is `(sh child1.sh ) &`. When you issue `child=$!` after that, you will not get the PID of `child1.sh`, but the PID of the shell under which `child1.sh` is running. In my opinion, this is not a problem because killing the shell in normal circumstances will kill all the subprocesses, as long you didn't launch these with `nohup`. – Pierre François May 19 '21 at 11:03
  • @PierreFrançois The process to be killed, is a node app and when I do what I suggested. I get this logged: Terminated. but then the process is still running in the background and my future attempts at running the parent script again fails, because the port is still busy. – Maths noob May 19 '21 at 11:13
  • 1
    @Mathsnoob: the fact that `child1.sh` is or runs a node app changes the problem substantially. Perhaps it doesn't exit gracefully when killed. You should mention node app as keyword and give more information regarding how the node app is exiting when killed for several types of signals. – Pierre François May 19 '21 at 11:49
  • @PierreFrançois hmm. the node app dies gracefully when I kill it without a sub-process tho. so I don't think it's anything inherent to the `child1` but more about how we kill it? :thinking – Maths noob May 19 '21 at 11:54
  • Could you provide the `child1.sh` script ? Or at least the command used to launch the node app ?I guess it would be better to get its pid directly. – Zilog80 May 19 '21 at 13:26

1 Answers1

1

From comments, i guess you're looking for that to kill the "right" shell :

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
kill "$child"

If you don't bother to mix stdout and stderr output from child1.

EDIT: But i guess it's better to kill the child processes of child1. You can do that if you have /proc mounted :

EDIT2: Get all the child's PIDs in order for display, note that kill will send SIGTERM to each of them and don't bother with order. And take care of processes with parenthesis or space(s) in cmd name.

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
child_proc=$(cat /proc/*/stat | sed 's/([^\)]*)*\( [TRS]\)/proc\1/' | sort -k4n,1n | awk -v parent=${child} -F' '  '
BEGIN {pids[0]=parent;}
{fnd=-1;for(i=0;i<=npids;i++) { if (pids[i]==$4) fnd=i; }
 if (fnd!=-1) { pids[npids++]=$1;;}
}
END { for(i=npids-1; i>=0; i--) print pids[i]; }')
echo "childs of child1 : $child_proc"
kill $child_proc

Both child1 and child2 shells will exit gracefully, only sub-processes of child1 should be killed.

EDIT3: If your ps client supports formatted output, a simpler and safer way avoiding sed and sort would then be :

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
child_proc=$(ps -o pid= -o ppid= -A | awk -v parent=${child} -F' '  '
BEGIN {pids[0]=parent;}
{fnd=-1;for(i=0;i<=npids;i++) { if (pids[i]==$2) fnd=i; }
 if (fnd!=-1) { pids[npids++]=$1;;}
}
END { for(i=npids-1; i>=0; i--) print pids[i]; }')
echo "childs of child1 : $child_proc"
kill $child_proc
Zilog80
  • 2,534
  • 2
  • 15
  • 20