日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux定时结束java进程_使用zt-exec库定时清理linux休眠进程

發(fā)布時間:2024/8/23 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux定时结束java进程_使用zt-exec库定时清理linux休眠进程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在幾個月前上線的一個采集項目,構架是基于java + selenium + chromedriver + chrome實現(xiàn)的采集。至于為哈不直接用jsoup或httpclient實現(xiàn)采集功能,是因為很多被采集頁面都是通過js來渲染內(nèi)容的,所以必須用webdriver+chrome來模擬真正的瀏覽器訪問來采集。

每隔一段時間就會出采集失敗問題,出現(xiàn)的時間沒有規(guī)律,可能兩天出現(xiàn)一次,可能一星期出現(xiàn)一次,可能一個月出現(xiàn)一次....

用linux top命令來查看服務器,會發(fā)現(xiàn)很多的chromedriver和chrome的進程

用ps命令查看服務器

ps -aux | grep chrome

存在狀態(tài)為Sl和Z的休眠進程和僵尸進程,啟動時間都不是當天,根據(jù)系統(tǒng)本身業(yè)務邏輯,進程不會存在運行那么長時間的情況。而java進程則全部都能正常關閉,但java進程啟動的chromedriver和chrome進程不一定能同時關閉,目前出現(xiàn)這種問題的原因未找到。

最初想用命令把卡死的進程查出來批量殺掉

ps -A -o stat,ppid,pid,cmd | grep -e '^[Zz]' | awk '{print $2}' | xargs kill -9 //殺死僵尸進程

結果發(fā)現(xiàn)只能查殺Z狀態(tài)的僵尸進程,Sl狀態(tài)的進程,一部分是正常的,一部分是需要殺死的(啟動時間為Nov07,Nov06的進程需要殺掉),至于哪些需要殺死,需要通過人工判斷啟動時間來確定是否需要殺掉進程。

之前一直忙時,都是先通過ps命令把chromedriver和chrome相關進程查詢出來,然后通過人工判斷進程是否屬于休眠狀態(tài),再手工kill殺掉進程。

最近有空了,本著能程序解決,就絕不要人工維護,把之前的手工殺休眠進程操作程序化。一開始想直接通過java的Runtime.getRuntime().exec()代碼調(diào)用linux命令操作的,不過在java常用類庫中(https://www.21doc.net/java/awesomejava#processes),找到zt-exec庫,可以簡化命令行調(diào)用操作。

程序化的代替人工維護實現(xiàn)定時清理休眠進程代碼如下:

import org.apache.log4j.Logger;

import org.apache.log4j.RollingFileAppender;

import org.zeroturnaround.exec.ProcessExecutor;

import org.zeroturnaround.exec.stream.LogOutputStream;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.List;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class ProcessKill {

private static Logger log = Logger.getLogger(ProcessKill.class);

public ProcessKill(){

}

public void run(){

try{

List> list = new ArrayList>();

// 先通過ps aux | grep chrome命令,獲取所有包含chrome文本內(nèi)容的進程

new ProcessExecutor().command("/bin/sh","-c","ps aux | grep chrome")

.redirectOutput(new LogOutputStream() {

protected void processLine(String line) {

log.info("line========" + line);

List lines = split(line.trim());

// 判斷進程啟動時間,確定是否為執(zhí)行超時休眠的進程

String time = lines.get(8);

String format = "[0-5][0-9]:[0-5][0-9]";

Pattern p = Pattern.compile(format);

Matcher m = p.matcher(time);

boolean result = m.find();

if(result == true) {

log.info("time ========" + time + " " + result);

}

else{

log.info("time xxxxxxxx" + time + " " + result);

list.add(lines);

}

}

})

.execute();

log.info("list========size:" + list.size());

list.forEach(l->{

log.info("list line========" + l);

});

for(int i = 0; i < list.size(); i++){

List strs = list.get(i);

try{

String pid = strs.get(1);

String stat = strs.get(7);

String time = strs.get(8);

String cmd = strs.get(10);

log.info("pid========" + pid + ", " + stat + ", " + time + ", " + cmd);

// 通過命令“kill -9 pid”殺掉進程

String output = new ProcessExecutor().command("/bin/sh","-c","kill -9 " + pid)

.readOutput(true).execute()

.outputUTF8();

log.info("kill========" + pid + ", " + output);

}

catch(Exception ex){

ex.printStackTrace();

}

}

}

catch(Exception e){

e.printStackTrace();

}

}

public List split(String s){

// ps aux | grep chrome 命令返回字段: USER,PID ,%CPU,%MEM,VSZ, RSS,TTY,STAT,START,TIME,COMMAND

List list = new ArrayList();

int blankCount = 0;

StringBuffer sff = new StringBuffer();

for(int i = 0; i < s.length(); i++){

char c = s.charAt(i);

if(list.size() < 10){

if(c != ' '){

sff.append(c);

blankCount = 0;

}

else if(c == ' '){

blankCount++;

}

if(blankCount == 1){

list.add(sff.toString());

sff = new StringBuffer();

}

}

else{

sff.append(c);

}

}

if(sff.length() > 0){

list.add(sff.toString());

}

return list;

}

public static void setLogFile(String name){

Logger rootLogger = Logger.getRootLogger();

Enumeration en = rootLogger.getAllAppenders();

while (en.hasMoreElements()){

Object obj = en.nextElement();

if(obj instanceof RollingFileAppender){

RollingFileAppender file = (RollingFileAppender)obj;

file.setFile(name + ".log");

file.activateOptions();

}

}

}

public static void main(String[] args){

setLogFile("log/" + ProcessKill.class.getSimpleName());

new ProcessKill().run();

}

}

文末記錄下ps和grep命令用法。

ps 顯示瞬間進程的狀態(tài)

參數(shù):

-A :所有的進程均顯示出來,與 -e 具有同樣的效用;

-a : 顯示現(xiàn)行終端機下的所有進程,包括其他用戶的進程;

-u :以用戶為主的進程狀態(tài) ;

x :通常與 a 這個參數(shù)一起使用,可列出較完整信息。

ps aux

USER:該進程屬于那個使用者賬號。

PID :該進程的進程ID號。

%CPU:該進程使用掉的 CPU 資源百分比;

%MEM:該進程所占用的物理內(nèi)存百分比;

VSZ :該進程使用掉的虛擬內(nèi)存量 (Kbytes)

RSS :該進程占用的固定的內(nèi)存量 (Kbytes)

TTY :該進程是在那個終端機上面運作,若與終端機無關,則顯示。另外, tty1-tty6 是本機上面的登入者程序,若為 pts/0 等等的,則表示為由網(wǎng)絡連接進主機的程序。

STAT:該程序目前的狀態(tài),主要的狀態(tài)有:

R :該程序目前正在運作,或者是可被運作;

S :該程序目前正在睡眠當中,但可被某些訊號(signal) 喚醒。

T :該程序目前正在偵測或者是停止了;

Z :該程序應該已經(jīng)終止,但是其父程序卻無法正常的終止他,造成 zombie (疆尸) 程序的狀態(tài)

START:該進程被觸發(fā)啟動的時間;

TIME :該進程實際使用 CPU 運作的時間。

COMMAND:該程序的實際指令。

ps -ef |grep java

UID :程序被該 UID 所擁有

PID :就是這個程序的 ID

PPID :則是其上級父程序的ID

C :CPU使用的資源百分比

STIME :系統(tǒng)啟動時間

TTY :登入者的終端機位置

TIME :使用掉的CPU時間。

CMD :所下達的是什么指令

grep命令的常用格式為:grep ?[選項] ?”模式“ ?[文件]

常用選項:

-E :開啟擴展(Extend)的正則表達式。

-i :忽略大小寫(ignore case)。

-v :反過來(invert),只打印沒有匹配的,而匹配的反而不打印。

-n :顯示行號

-w :被匹配的文本只能是單詞,而不能是單詞中的某一部分,如文本中有l(wèi)iker,而我搜尋的只是like,就可以使用-w選項來避免匹配liker

-c :顯示總共有多少行被匹配到了,而不是顯示被匹配到的內(nèi)容,注意如果同時使用-cv選項是顯示有多少行沒有被匹配到。

-o :只顯示被模式匹配到的字符串。

--color :將匹配到的內(nèi)容以顏色高亮顯示。

-A n:顯示匹配到的字符串所在的行及其后n行,after

-B n:顯示匹配到的字符串所在的行及其前n行,before

-C n:顯示匹配到的字符串所在的行及其前后各n行,context

查看系統(tǒng)狀態(tài)下的僵尸進程:

ps -ef | grep defunct ?后面尖括號里是defunct的都是僵尸進程。

ps aux | grep -w 'Z' 其中狀態(tài)為Z的代表僵尸進程。

總結

以上是生活随笔為你收集整理的linux定时结束java进程_使用zt-exec库定时清理linux休眠进程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。