4

我有一个脚本可以跟踪一个进程,如果该进程终止,它将重新生成它。如果通过给跟踪脚本一个 sigterm(例如)被告知这样做,我希望跟踪脚本也终止该进程。换句话说,如果我终止跟踪脚本,它也应该终止它正在跟踪的进程,不再重生并退出。

将几个帖子拼凑在一起(我认为这是最佳实践,例如不使用 PID 文件),我得到以下信息:

#!/bin/bash

DESC="Foo Manager"
EXEC="python /myPath/bin/FooManager.pyc"

trap "BREAK=1;pkill -HUP -P $BASHPID;exit 0" SIGHUP SIGINT SIGTERM

until $EXEC
do
    echo "Server $DESC crashed with exit code $?.  Restarting..." >&2
    ((BREAK!=0)) && echo "Breaking" && exit 1
    sleep 1
done

所以,现在如果我在一个 xterm 中运行这个脚本。然后在另一个 xterm 中,我发送脚本如下:

kill -HUP <tracking_script_pid>  # Doesn't work.
kill -TERM <tracking_script_pid>  #Doesn't work.

跟踪脚本没有结束或任何事情。如果我从命令行运行 FooManager.pyc,它将在 SIGHUP 和 SIGTERM 上死掉。无论如何,我在这里做错了什么,也许有一种完全不同的方法可以做到这一点?

谢谢。

4

1 回答 1

3

从手册:

如果 Bash 正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前不会执行陷阱。当 Bash 通过内置函数等待异步命令时wait,接收到已设置陷阱的信号将导致wait内置函数立即返回,退出状态大于 128,然后立即执行陷阱。

重点是我的。

因此,在您的情况下,当您的命令正在执行时,Bash 将等到它结束后再触发陷阱。

要解决此问题,您需要将程序作为作业运行,然后等待它。如果您的程序永远不会以大于 128 的返回码退出,您可以简化以下代码,但我没有做出这样的假设:

#!/bin/bash

desc="Foo Manager"
to_exec=( python "/myPath/bin/FooManager.pyc" )

trap 'trap_triggered=true' SIGHUP SIGINT SIGTERM

trap_triggered=false
while ! $trap_triggered; do
   "${to_exec[@]}" &
   job_pid=$!
   wait $job_pid
   job_ret=$?
   if [[ $job_ret = 0 ]]; then
      echo >&2 "Job ended gracefully with no errors... quitting..."
      break
   elif ! $trap_triggered; then
      echo >&2 "Server $desc crashed with exit code $job_ret. Restarting..."
   else
      printf >&2 "Received fatal signal... "
      if kill -0 $job_pid >&/dev/null; then
          printf >&2 "killing job $job_pid... "
          kill $job_pid
          wait $job_pid
      fi
      printf >&2 "quitting...\n"
   fi
done

笔记。

  1. 我使用了小写的变量名,因为大写被认为是不好的做法:它们可能与 Bash 的保留名称或环境变量发生冲突。
  2. 我没有使用字符串来存储命令,而是使用数组。对于字符串,如果您想将空格等有趣的字符作为参数传递,您将遇到很多问题。使用正确引用的数组,您不会有任何问题。(有些人会争辩说使用函数会更好。)
于 2014-12-22T18:30:25.877 回答