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

时间:2018-12-10 20:27:41

标签: bash loops kill foreground

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

这是我所拥有的:

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

这确实产生了http-server,但是当我用Ctrl C退出时,进程不会被杀死。

我首先没有循环就实现了这一点,并添加了&& fg我可以使用Ctrl + C终止进程

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

我的循环解决方案有可能实现类似的目的吗?

编辑:系统为macOS

1 个答案:

答案 0 :(得分:3)

一种简单的方法-尽管不是完全可靠,但是如果进程死了并且为其分配了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"