Java調用 shell腳本阻塞

  Java在調用Shell時,要不斷讀取進程中標準輸出和錯誤輸出流的信息,否則緩衝區被寫滿就會造成子進程阻塞而無法繼續運行下去,可起兩個線程不斷讀取標準輸出、錯誤流信息而不被阻塞

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import org.apache.commons.io.IOUtils;

import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;


public class RmtShellExecutor {

	
	private Connection conn;
	private String ip;
	private String usr;
	private String psword;
	private String charset = Charset.defaultCharset().toString();

	private static final int TIME_OUT = 1000 * 5 * 60;

	public RmtShellExecutor(String ip, String usr, String ps) {
		this.ip = ip;
		this.usr = usr;
		this.psword = ps;
	}

	private boolean login() throws IOException {
		conn = new Connection(ip);
		conn.connect();
		return conn.authenticateWithPassword(usr, psword);
	}

	//本地執行方法
	public static void execLocal(String cmd) {
	       try {
				Process proc = Runtime.getRuntime().exec(cmd);
				StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
				StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
				errorGobbler.start();
				outputGobbler.start();
				int exitVal = proc.waitFor();
		        System.out.println("ExitValue: " + exitVal);
		     } catch (Exception e) {
				  e.printStackTrace();
		     } 
			
		}
        
    //遠程執行方法
	public int execRemote(String cmds){
		InputStream stdOut = null;
		InputStream stdErr = null;
		int ret = -1;
		try {
			if (login()) {
				// Open a new {@link Session} on this connection
				Session session = conn.openSession();
				// Execute a command on the remote machine.
				session.execCommand(cmds);

				GobblerThread gtOut = new GobblerThread(session.getStdout(),"STD_OUT");
				GobblerThread gtErr = new GobblerThread(session.getStderr(),"STD_ERR");
				gtOut.start();
				gtErr.start();

				session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
				ret = session.getExitStatus();
			} else {
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		finally {
			if (conn != null) {
				conn.close();
			}
			IOUtils.closeQuietly(stdOut);
			IOUtils.closeQuietly(stdErr);
		}
		return ret;
	}

	public static void main(String args[]) throws Exception {
		RmtShellExecutor exe = new RmtShellExecutor("192.168.3.5", "test",
				"123456");
		System.out.println(exe.execRemote("sh /home/test/cmd.sh company=32"));
	}
}

class GobblerThread extends Thread
{
    InputStream is;
    String type;
    
    GobblerThread(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }
    
    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(line);    
            } catch (IOException e)
              {
                e.printStackTrace();  
              }
    }
}

execLocal 爲本地調用cmd的方法

exeRemote 可利用ssh登錄遠程機器調用cmd的方法


參考文章:http://www.linuxidc.com/Linux/2014-04/99557.htm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章