我正在输入一个小的 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 的 ac 程序解决了我的问题。