我正在运行一个基本上运行一堆服务器进行本地测试的脚本。
这些罐子在不同的屏幕上运行,因为它们需要全部独立接受键盘输入。为此,我使用了屏幕。
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。
在使用退出屏幕命令之前
使用退出屏幕命令后
他们也会永远用武力戒掉gui杀死
其他信息:
因为服务器正在接受键盘输入,所有发送到屏幕的命令都会被服务器摄取。 他们确实有输入退出但我不想信任服务器退出。
所以我的问题是:
是否有办法让屏幕在终止时终止其中所有正在运行的进程?
如果没有办法将ctrl-c发送到特定的屏幕?
如果没有,有没有办法在屏幕本身没有运行命令的情况下查看某个屏幕的运行过程是什么? (然后我可以使用kill)
tl; dr当我杀死屏幕时,运行进程开始使用我所有的cpu并且不会终止。我想让它终止。
答案 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