【问题标题】:Parallel processes in bash, kill with Ctrl Cbash 中的并行进程,使用 Ctrl C 终止
【发布时间】:2019-05-11 19:03:32
【问题描述】:

刚刚制作了我的第一个 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

【问题讨论】:

  • 最佳实践是根本不这样做,而是——例如——每个实例都有一个单独的 systemd 服务。
  • (...因为已经明确说明您使用的是 MacOS,所以它会被启动,而不是 systemd)。
  • xargs 也可能是一个很好的解决方案 :) stackoverflow.com/questions/28357997/…

标签: bash loops kill foreground


【解决方案1】:

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

【讨论】:

  • 谢谢,您能否详细说明为什么这不是最佳实践以及 systemd 服务如何更好?
  • 因此,您可以配置类似 http-server@.service 的服务,其中当您“systemctl start http-server@8001”时,它会将实例名称 8001 替换为配置的命令。这样您就可以单独查询每个实例,为每个实例配置重启行为,为每个实例命令关闭或启动时的行为,请求任何单个实例的日志,等等。
  • 你的 shell 脚本不知道运行在 8005 端口上的 http-server 实例何时死掉——一个监督系统(其中 systemd 只是一个——runit、supervisord、upstart、launchd 和 c . 是许多其他可用的服务之一)观看该服务将持续wait()ing,并会在发生的那一刻得到通知/唤醒。拥有系统范围的名称还意味着您可以锁定多个“免费”启动的实例。
  • 我接受您的回答作为我自己的进一步研究案例,因为我缺乏正确验证它的基本技能。第一个代码示例在没有返回值的情况下简单地完成,第二个我在 OSX 上缺少flock。不是说有什么不对,我只是缺乏判断力。非常感谢您的指点,希望我能尽快做出更多贡献。
  • 啊,对了——我们确实实际上需要wait 来处理进程。适当修改。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 2014-07-10
  • 2021-02-23
  • 2013-02-18
  • 2018-11-17
相关资源
最近更新 更多