2017-06-29 91 views
0

我有一个运行java应用程序并保持运行前景的脚本。 我想要实现的是在发出Ctrl + c时关闭java应用程序。杀死Java应用程序进程树从Bash脚本运行Ctrl + C

假设是这样的:

bash的文件-1:

trap "stopit; exit" SIGINT 
echo "Going to run java app" 
source bash-file-2.sh 

bash-file-2.sh:

exec java -jar myapp.jar 
  • 的stopit()函数只是看起来对于.pid文件,杀死该进程。在后台运行应用程序时它工作正常。

这里发生的是,当我发出Ctrl + c时,我退出控制台模式,但应用程序一直在后台运行。我猜这是因为'exec'命令导致应用程序在另一个shell中运行。它是否正确?

在这种情况下,如何捕获ctrl + c并调用stopit函数?

编辑

,我运行的Java应用程序是一个包装罐子调用实际的jar文件。

这将是这样的:

bash1 -> bash2 -> wrapper.jar -> myapp.jar 
+0

'exec'取代你的过程中与其他,'stopit'在这个过程中不会存在很长时间,但是你可能并不真的需要'exec',你只需要'java ...',它会执行那个命令,就像你输入了它一样 –

+0

@EricRenouf我编辑了这个问题,我试过了你说,并意识到问题来自调用另一个jar的jar。希望如此? –

+0

调用如何发生,我的意思是第二个jar – Marged

回答

0

如果你的子进程(Java应用程序)会生成新的进程,你需要杀死在您的应用程序根的完整进程树。

首先,定义一个(通用)辅助killtree功能:

#!/bin/bash 

# Prints all descendant of a process `ppid`, level-wise, bottom-up. 
# Usage: _get_proc_descendants ppid 
function _get_proc_descendants() { 
    local pid ppid="$1" 
    local children=$(ps hopid --ppid "$ppid") 
    for pid in $children; do 
     echo "$pid" 
     _get_proc_descendants "$pid" 
    done 
} 

# Kills all process trees rooted at each of the `pid`s given, 
# along with all of their ancestors. 
# Usage: killtree [pid1 pid2 ...] 
function killtree() { 
    while [ "$#" -gt 0 ]; do 
     local pids=("$1" $(_get_proc_descendants "$1")) 
     kill -TERM "${pids[@]}" &>/dev/null 
     shift 
    done 
} 

然后,在你trap,说:

trap "killtree $java_app_pid; exit" SIGINT 

其中$java_app_pid是你的Java应用程序的PID(你说你有一个pid文件)。

或者,您也可以定义killtree只杀死的PID的后裔:

function killtree() { 
    while [ "$#" -gt 0 ]; do 
     local pids=($(_get_proc_descendants "$1")) 
     kill -TERM "${pids[@]}" &>/dev/null 
     shift 
    done 
} 

,并简化您trap(杀死脚本的孩子):

trap "killtree $$; exit" SIGINT