Параллельные процессы в bash, убить с помощью Ctrl C - PullRequest
0 голосов
/ 10 декабря 2018

только что сделал мой первый скрипт bash.Он запускает процесс http-server параллельно для каждой папки в определенном каталоге.

Вот что у меня есть:

PORT=8001
cd websitesfolder
for d in */ ; do
  http-server $d -p $PORT &
  let "PORT++" 
done

Это порождает http-server s, но когда явыйти с помощью Ctrl C. процессы не будут убиты.

Сначала я реализовал это без цикла и, добавив && fg, смог убить процессы с помощью Ctrl + C

http-server dir1 -p 8001 & http-server dir2 -p 8002 && fg

Возможно ли нечто подобное с моим зацикленным решением?

edit: система macOS

1 Ответ

0 голосов
/ 10 декабря 2018

Простой подход - хотя и не совсем надежный, если процесс умирает и ему назначают что-то еще свой номер PID - это просто поддерживать массив PID:

#!/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лучший подход - иметь файл блокировки на порт или использовать fuser -k для уничтожения процессов, которые фактически удерживают порты открытыми, а не предполагать, что вы знаете PID:

#!/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"
...