Reputation: 3080
Just made my first bash script. It spawns a http-server
process in parallel for each folder in a certain directory.
Here is what I have:
PORT=8001
cd websitesfolder
for d in */ ; do
http-server $d -p $PORT &
let "PORT++"
done
This does spawn the http-server
s, but when I exit with Ctrl C, the processes are not killed.
I implemented this without a loop first, and adding && fg
I was able to kill the processes using Ctrl+C
http-server dir1 -p 8001 & http-server dir2 -p 8002 && fg
Is something similar possible with my looped solution?
edit: system is macOS
Upvotes: 1
Views: 1436
Reputation: 295443
A simple approach -- albeit not completely reliable, should a process die and have something else be assigned its PID number -- is simply to maintain an array of PIDs:
#!/usr/bin/env bash
pids=( )
port=8001
graceful_shutdown() {
(( ${#pids[@]} )) && kill "${pids[@]}"
}
cd websitesfolder || exit
for d in */ ; do
http-server "$d" -p "$port" & pids+=( "$!" )
(( ++port ))
done
trap graceful_shutdown EXIT
for pid in "${pids[@]}"; do
wait "$pid" || (( retval |= $? ))
done
exit "$retval"
A better approach is to have a lockfile per port, or to use fuser -k
to kill the processes that actually hold the ports open directly, rather than assuming that you know the PIDs:
#!/usr/bin/env bash
graceful_shutdown() {
fuser -k "$lockdir"/*
}
lockdir=/var/run/mydir # this needs to exist
port=8001
pids=( )
cd websitesfolder || exit
for d in */; do
(exec 3>"$lockdir/$port" &&
flock -x 3 &&
exec http-server "$d" -p "$port") & pids+=( "$!" )
done
trap graceful_shutdown EXIT
for pid in "${pids[@]}"; do
wait "$pid" || (( retval |= $? ))
done
exit "$retval"
Upvotes: 4