我正在键入一个小的bash脚本,它应该克隆一个git存储库,签出一个特定的硬编码分支并监听一些新的提交。如果找到新的提交,脚本应该杀死正在运行的' MyApp'的实例,执行git pull并最终使用gradle构建它。它也应该再次通过gradle开始。
是的,它是一个带有gradle构建文件的java应用程序。
这是我的代码:
##!/bin/bash
# GitHub Repository and Paths
GLOBAL_REPOSITORY="..."
LOCAL_REPOSITORY="..."
# Go to the repository
cd $LOCAL_REPOSITORY
# Clone the git repository if not already done
if [ ! -d "$LOCAL_REPOSITORY/.git" ]
then
git clone $GLOBAL_REPOSITORY $LOCAL_REPOSITORY
git checkout dev
fi
# Pull and build if there are new commits
LAST_GLOBAL_COMMIT=""
LAST_LOCAL_COMMIT=""
CHILDS_PID=""
while true; do
git fetch origin
LAST_GLOBAL_COMMIT="$(git rev-parse origin/dev)"
LAST_LOCAL_COMMIT="$(git rev-parse dev)"
if [ "$LAST_GLOBAL_COMMIT" != "$LAST_LOCAL_COMMIT" ]
then
if [ "$CHILDS_PID != "" ]
then
kill 9 "$CHILDS_PID" # Line 33
fi
LAST_LOCAL_COMMIT="$LAST_GLOBAL_COMMIT"
git pull origin dev
gradle
CHILDS_PID="$(gnome-terminal -e \"gradle run\" & echo $!)"
fi
sleep 300
done
出现的问题是子终端和MyApp仍在运行。只有gradle似乎死了。但我想杀死所有子进程,然后再次运行它们。只有运行我脚本的终端才不会被杀死。
在实际情况中,进程树应如下所示:
Main Terminal (Running the script)
|
|
Child Terminal
|
|
Gradle run
|
|
MyApplication
我的问题是我怎么能一次杀死所有这些进程,除了第33行顶部的终端?
修改
这里的不同之处在于我搜索了一种方法来查找子树的主节点并在第二步中将其终止。
但我发现如果一个bash实例正在调用gnome-terminal或任何其他终端或tty,它正在进行一个初始化分叉终端的进程。
因此,例如,terminal_1的PID为42,我通过它启动另一个终端,然后它将启动一个PID为43的init进程,该进程初始化将具有PID为44的terminal_2。但是terminal_1只获得了43作为返回值。在此之后,init进程终止,如果你试图杀死PID 43,它逻辑上说没有进程那个PID。
此时跟踪不可能,我通过编写一个自己使用fork的c程序解决了我的问题。