我們的hive web是調用polestar restful service(https://github.com/lalaguozhe/polestar-1)來執行具體的hive或者shark語句的,這幾天有用戶說hive web上的kill按鈕失效了,雖然已經顯示停止了查詢,但是其實提交到jobtracker的mapred job或者spark worker節點上作業還在running。我看了下,確實有這個問題。
polestar對於每一條query執行的命令如下
sudo -u yukang.chen bash -c "echo \$\$ > /tmp/hive.pid;source /etc/profile;export KRB5CCNAME=/tmp/krb5cc_500;hive -e 'select count(1) from hippolog'"
先sudo成提交query的用戶,將用戶bash -c進程號輸出到一個文件下,設置好環境變量,再起一個java子進程執行語句
ps: 輸出進程號到一個文件下是為了之後要kill作業用,這邊由於$符號在雙引號裡面,所以會被替換成當前用戶的bash進程號,而我們需要獲取的是sudo成指定用戶執行命令的進程號,所以要對$符號加上反斜槓來轉義
yukang.chen用戶終端看ps xuf
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1158 30497 0.0 0.0 106204 1556 pts/25 S+ 15:08 0:00 bash -c echo $$ > /tmp/hive.pid;source /etc/profile;export KRB5CCNAME=/tmp/krb5cc_500;hive -e 'select count(1) from hippolog' 1158 30504 29.5 2.2 9644528 178476 pts/25 Sl+ 15:08 0:28 \_ /usr/local/jdk/bin/java -Dproc_jar -Xmx7000m -server -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -Dhadoop.log.dir=/data/logs
java進程的PPID就是bash -c的進程號30497(也是/tmp/hive.pid的值),構成父子進程關系
用戶前端按下kill按鈕後,後端會sudo成指定用戶,先讀取pid文件,再kill -9 pid
觀察發現父進程是被kill掉了,但是子進程還活著,而且PPID已經換成為1,也就是init(1)進程
查看命令ps -p 30504 -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1158 30504 1 16 80 0 - 2411132 futex_ pts/25 00:00:28 java
這種kill方式導致了雖然kill了父進程,但是真正執行hive和shark的java進程還活著,沒有退出
解決方式有兩種:
1. 使用kill -- -<PPID>
這種方式執行語句不變, 更改kill命令,PPID前是一個負號,這樣會將以PPID為首的整個進程樹(包括子進程)都kill掉
2. 使用exec命令
這種方式需要更執行語句,在hive命令前加上exec
exec命令會將子進程替換當前進程執行(bash -c 替換成hive java進程),如果hive之後還有後續命令都不會執行.
執行語句如下:
sudo -u yukang.chen bash -c "echo \$\$ > /tmp/hive.pid;source /etc/profile;export B5CCNAME=/tmp/krb5cc_500;exec hive -e 'select count(1) from hippolog'"
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1158 32068 59.0 3.6 9577964 290476 pts/25 Sl+ 15:18 0:28 /usr/local/jdk/bin/java -Dproc_jar -Xmx7000m -server -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -Dhadoop.log.dir=/data/logs -Dh
因為child java process替換了parent bash -c process,所以看到的只有一個java process,這樣我們kill的話,就很容易了,不需要kill子進程