2017-06-29 86 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