bash 中的并行进程,使用 Ctrl C 终止

Parallel processes in bash, kill with Ctrl C

刚刚制作了我的第一个 bash 脚本。它为特定目录中的每个文件夹并行生成一个 http-server 进程。

这是我的:

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

这确实产生了 http-servers,但是当我使用 Ctrl C 退出时,进程没有被终止。

我先在没有循环的情况下实现了这个,然后添加 && fg 我能够使用 Ctrl+C

终止进程
http-server dir1 -p 8001 & http-server dir2 -p 8002 && fg

我的循环解决方案是否有类似的可能?

编辑:系统为 macOS

一个简单的方法——尽管不完全可靠,如果一个进程死了并且有其他东西被分配了它的 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"

更好的方法是为每个端口设置一个锁定文件,或者使用 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"