杀死屏幕但java进程没有结束

时间:2014-10-17 23:05:57

标签: java bash gnu-screen kill-process

我正在运行一个基本上运行一堆服务器进行本地测试的脚本。

这些罐子在不同的屏幕上运行,因为它们需要全部独立接受键盘输入。为此,我使用了屏幕。

command1="java -jar $fullPath"
screen -d -m -S "${screenName[$i]}" bash -c "$command1"

效果很好!

然后我需要一种杀死所有服务器的方法

所以我写了一个执行该操作的脚本

for session in $(screen -ls | grep -o "[0-9]*\.${screenName[$i]}")
do
    screen -X -S "$session" quit
    echo "killing screen $session"
done

屏幕被杀死效果很好。 但是第二个我做的那个java突然占用了我100%的CPU。

在使用退出屏幕命令之前

The servers running normally

使用退出屏幕命令后

enter image description here

他们也会永远用武力戒掉gui杀死

enter image description here

其他信息:

  • 服务器正在使用在一个java线程上运行的Jetty。然后另一个线程就坐下来等待键盘输入。
  • 显然这是在mac上运行,脚本是bash所以我想要一个适用于mac和linux的bash解决方案。
  • 它们也是使用java 7构建的,但使用java 8
  • 运行

因为服务器正在接受键盘输入,所有发送到屏幕的命令都会被服务器摄取。 他们确实有输入退出但我不想信任服务器退出。

所以我的问题是:

  • 是否有办法让屏幕在终止时终止其中所有正在运行的进程?

  • 如果没有办法将ctrl-c发送到特定的屏幕?

  • 如果没有,有没有办法在屏幕本身没有运行命令的情况下查看某个屏幕的运行过程是什么? (然后我可以使用kill)

tl; dr当我杀死屏幕时,运行进程开始使用我所有的cpu并且不会终止。我想让它终止。

1 个答案:

答案 0 :(得分:2)

自己制定解决方案。

简而言之,它找到了屏幕进程并找到所有java进程然后查找其祖父进程是一个屏幕的java进程。

它非常低效,因为它为每个屏幕循环遍历数组。所以基本上是O(n ^ 2),但很少,所以它对我有用!

代码:

length=$(expr ${#screenName[@]} - 1)

# gets all of the java processes and their grand parents
# the reason is that the screen makes 2 processes one is the java process and the other is the parent process
# I can't grab a children in mac for some reason BUT i can grab the parent process
javaPs=()
javaGpPs=()
for javaId in $(pgrep java)
do
    #echo
    #echo $javaId
    #echo $(ps -o ppid= $javaId)
    #echo $(ps -o ppid= $(ps -o ppid= $javaId))
    javaPs+=($javaId)
    javaGpPs+=($(ps -o ppid= $(ps -o ppid= $javaId)))
done

echo "Child procressed followed by screen processes"
echo ${javaPs[@]}
echo ${javaGpPs[@]}
#gets the index of an element in an array
#search term is first followed by the array
#note that becuase it returns by echo you can not add any debug statements into this function
search() {
    local i=1;
    searchTerm="${1}"
    shift #moves over the argument looking
    array=("${@}") #grabs the rest of the args as an array (which is an array)
    for str in ${array[@]}; do
        if [ "$str" = "$searchTerm" ]; then
            echo $((i - 1)) #should reference the correct index (0 to something)
            return
        else
            ((i++))
        fi
    done
    echo "-1"
}

for (( i=0; i<=$length; i++ ))
do
    #looks to see if there are multiple screens with the same name
    for session in $(screen -ls | grep -o "[0-9]*\.${screenName[$i]}")
    do
        echo
        echo "killing screen $session"
        IFS='.' read -ra ADDR <<< "$session" #splits the id from the name
        pid=${ADDR[0]}
        screen -X -S "$session" quit # exit session

        # now we kill the still running java process (because it will not exist for some reason)
        itemIndex=$(echo $(search "${pid}" "${javaGpPs[@]}"))
        javaId=${javaPs[$itemIndex]}
        # the process that is being killed
        echo "killing java process"
        echo $(ps -p $javaId)
        kill -9 $javaId
        sleep 1
    done
done

echo
echo "All process should now be dead doing extra clean up now"
screen -wipe #remove all dead screens