linux下,利用shell和js实现进程信息收集和控制的简单方法

原创
2015/12/03 16:45
阅读数 1.2K

一、目的:

1、收集java进程中那些外部很难获取的信息

2、控制java进程;

二、结构:

三、控制过程:

1、通过shell命令,向js发送命令字符串;

2、js将命令字符串通过socket传递给java进程内的监听器;

3、监听器根据命令调用相关的采集器和控制器;实现控制或采集;

四、实现效果:

五:代码:

1、shell脚本:sctl.sh

#!/usr/bin/env bash

function check_java (){
    JAVA_PATH=`which java 2>/dev/null`
    if [ "x$JAVA_PATH" != "x" ]; then
        _javacmd=java
    elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]];  then
        _javacmd="$JAVA_HOME/bin/java"
    else
        echo "ERROR: java Not find!"
    fi

    if [[ "$_javacmd" ]]; then
        version=$("$_javacmd" -version 2>&1 | awk -F '"' '/version/ {print $2}')
        if [[ "$version" < "1.6" ]]; then
            echo "download rhino.jar"
        elif [[ "$version" < "1.8" ]]; then
            jsi='jrunscript -f'
            WITH_ARGS=''
        else
            jsi='jjs -scripting'
            WITH_ARGS='--'
        fi
    fi
}
check_java

$jsi server.js $WITH_ARGS $@

2、js代码:server.js

(function(){
    var root = typeof self == 'object' && self.self === self && self ||
        typeof global == 'object' && global.global === global && global ||
        this;
    var args = root.arguments;
    var command = args.pop();
    var s = new java.net.Socket("localhost", 9090);
    var os = new java.io.PrintWriter(s.getOutputStream(), true);
    var is = new java.io.BufferedReader(new java.io.InputStreamReader(s.getInputStream()));
    var write = function(str){
        new java.io.PrintWriter(os).println(str);
        os.flush();
    };
    if(command) write(command);
    var connected = true;
    while(connected){
        var msg = is.readLine();
        if(msg=="#END#"){
            connected =false;
            print(msg);
        }else if(msg==null) {
            connected = false;
        } else {
            print(msg);
        }
    }
})();

3、监听器代码:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Created with IntelliJ IDEA.
 * Desc: 管理端口服务
 * 负责接收管理请求命令,并返回命令结果
 */
public class ControlListener extends Thread {
    private final static Logger logger = LogManager.getLogger("net");
    boolean flag = true;
    int consolePort = 9090;

    public ControlListener(String name, int port) {
        super(name);
        consolePort = port;
    }

    public void interrupt() {
        this.flag = false;
        super.interrupt();
    }

    public void run() {

        logger.info("control listener started at " + consolePort);

        ServerSocket listener = null;
        try {
            listener = new ServerSocket(consolePort);
            while (flag) {

                Socket socket = listener.accept();
                BufferedReader socketReader =
                        new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String str = socketReader.readLine();
                if (str == null) {
                    continue;
                }
                if (!str.equals("exit")) {
                    logger.info("accept control CMD: " + str);
                    String returnStr = Console.execute(str.trim());
                    socket.getOutputStream().write((returnStr + "\r\n#END#\r\n").getBytes());
                } else {
                    socketReader.close();
                }
            }
            logger.info("control listener stoped");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (listener!=null) {
                    listener.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4、主控类代码:

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created with IntelliJ IDEA.
 * Desc: 主控类
 */
public class Console {

    private final static Map<String, IControl> consoleCmdFactory = new ConcurrentHashMap<>();

    public static void regCmd(String cmd,IControl cls){
        if (null != cmd && null != cls) {
            consoleCmdFactory.put(cmd, cls);
        }
    }

    public static String execute(String cmd){
        IControl control = consoleCmdFactory.get(cmd);
        if (null == control){
            return "非法命令请求!";
        }else{
            return control.execute();
        }
    }

    public static void close(){
        for(Map.Entry<String,IControl> entry : consoleCmdFactory.entrySet()){
            try {
                entry.getValue().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


}

5、控制器或收集器接口:

import java.io.Closeable;

/**
 * Desc: 控制进程接口,所有的采集器,控制器都需要实现此接口的execute和close方法.
 * 1,execute方法返回的String就是所要打印的系统信息,需要业务端自行进行定义.
 * 2,close方法是考虑在收集系统信息时可能会打开一些需要关闭的内容(比如线程),在close方法中进行释放.
 */
public interface IControl extends Closeable{
    /**
     * execute方法返回的String就是所要打印的系统信息,需要业务端自行进行定义.
     * @return 返回执行结果字符串
     */
    String execute ();
}

6、一个收集器的实例:

import com.gvsoft.communication.console.IControl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created with IntelliJ IDEA.
 * Desc: 服务端并发情况收集器
 */
public class ConcurrentGather implements IControl {

    private final static Logger logger = LogManager.getLogger("net");
    ConcurrentCounter concurrentCounter = null;
    private static AtomicInteger readCount = new AtomicInteger(0);
    private static AtomicInteger writeCount = new AtomicInteger(0);

    private Integer concurrentReadCount;
    private Integer concurrentWriteCount;

    public ConcurrentGather() {
        if (null == concurrentCounter) {
            concurrentCounter = new ConcurrentCounter("ConcurrentCounter");
            concurrentCounter.start();
        }
    }

    public static void increasingRead() {
        readCount.incrementAndGet();

    }

    public static void increasingWrite() {
        writeCount.incrementAndGet();
    }

    public Integer getAvgReadCount() {
        return concurrentReadCount;
    }

    public Integer getAvgWriteCount() {
        return concurrentWriteCount;
    }

    @Override
    public String execute() {
        String statusStr;
        statusStr = "并发状态收集器打印结果如下:\r\n" + "每秒读取包(包含通讯层):" + getAvgReadCount() + "\r\n" +
                "每秒写入包(包含通讯层):" + getAvgWriteCount() + "\r\n";
        return statusStr;
    }

    @Override
    public void close() throws IOException {
        concurrentCounter.interrupt();
    }

    class ConcurrentCounter extends Thread {

        ConcurrentCounter(String name) {
            super(name);
        }

        private boolean flag = true;

        @Override
        public void interrupt() {
            this.flag = false;
            super.interrupt();
        }

        @Override
        public void run() {
            Integer cycle = 10;
            while (flag) {
                concurrentReadCount = readCount.get() / cycle;
                concurrentWriteCount = writeCount.get() / cycle;
                readCount.set(0);
                writeCount.set(0);
                try {
                    Thread.sleep(cycle * 1000);
                } catch (InterruptedException e) {
                    logger.info(this.getName() + "线程已经被中止!");
                }
            }
        }
    }
}

具体代码请参看:http://git.oschina.net/java616/

可以通过Console的静态方法regCmd注册新的命令字符串和对应的实现类;通过继承IControl接口实现这些类。

展开阅读全文
打赏
0
43 收藏
分享
加载中
更多评论
打赏
0 评论
43 收藏
0
分享
返回顶部
顶部