如何在bash中重启进程或在命令中终止它?

时间:2014-12-22 17:45:26

标签: bash kill restart sigkill

我有一个跟踪进程的脚本,如果该进程终止,它将重新生成它。我希望跟踪脚本也可以通过为跟踪脚本提供一个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上死亡。无论如何,我在这里可能做错了什么,也许还有不同的方法可以做到这一点?

感谢。

1 个答案:

答案 0 :(得分:3)

从手册:

  

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

强调是我的。

所以在你的情况下,当你的命令正在执行时,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. 我没有使用字符串来存储命令,而是使用数组。使用字符串,如果你想让像空格一样的有趣字符作为参数传递,你会遇到很多问题。使用正确引用的数组,您不会遇到任何问题。 (有些人认为使用函数会更好。)