1.使用Apache Common Execs库封装AbstractCommonExecs
测试类是GbkCommonExecs
2.完整代码:
public abstract class AbstractCommonExecs {
private Logger log = LoggerFactory.getLogger(AbstractCommonExecs.class);
private static final String DEFAULT_ENCODING = "UTF-8";
private String encoding = DEFAULT_ENCODING;
private static final String DEFAULT_CODEINFO_KEY = "CODEINFO";
private String codeInfokey = DEFAULT_CODEINFO_KEY;
private String bin;
private List<String> arguments;
public AbstractCommonExecs(String bin, List<String> arguments) {
this.bin = bin;
this.arguments = arguments;
}
public ExecResult exec() throws CmdRunException{
ExecResult er = new ExecResult();
try {
Executor executor = getExecutor();
CommandLine cmdLine = getCommandLine();
log.info("Executing script {}",cmdLine.toString());
if(supportWatchdog()) {
executor.setWatchdog(getWatchdog());
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PipedOutputStream outputStream = new PipedOutputStream();
//ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream,errorStream);
executor.setStreamHandler(streamHandler);
int ret = executor.execute(cmdLine);
BufferedReader br = new BufferedReader(new InputStreamReader(new PipedInputStream(outputStream), getEncoding()));
StringBuilder sb = new StringBuilder();
String line = null;
while((line = br.readLine()) != null) {
sb.append(line+"\n");
if(line.startsWith(getCodeInfokey())) {
er.setCodeInfo(line);
}
}
String stdout = sb.toString();
//String stdout = outputStream.toString(getEncoding());
String stderr = errorStream.toString(getEncoding());
er.setStderr(stderr);
log.info("output from script {} is {}", this.bin, stdout);
log.info("error output from script {} is {}", this.bin, stderr);
log.info("exit code from script {} is {}", this.bin, ret);
er.setStdout(stdout);
er.setExitCode(ret);
return er;
} catch (ExecuteException e) {
throw new CmdRunException("", e);
} catch (IOException e) {
throw new CmdRunException("", e);
}
}
public Executor getExecutor() {
Executor executor = new DefaultExecutor();
executor.setWorkingDirectory(new File(this.bin).getParentFile());
return executor;
}
public CommandLine getCommandLine() {
String fullCommand = bin + join(arguments);
if(isWindowSystem()) {
fullCommand = "cmd /c " + fullCommand;
}
return CommandLine.parse(fullCommand);
}
protected String join(List<String> arguments) {
if(arguments == null || arguments.isEmpty()) {
return "";
}
StringBuilder sb = new StringBuilder();
for(String arg : arguments) {
sb.append(" ").append(arg);
}
return sb.toString();
}
protected boolean isWindowSystem(){
boolean isWindowSystem = false;
Properties props=System.getProperties();
String osName = props.getProperty("os.name");
if(osName != null){
isWindowSystem = osName.contains("Windows") || osName.contains("windows");
}
//return isWindowSystem;
return false; //交给apache commons exec来判断
}
/**
* @return the encoding
*/
public String getEncoding() {
return encoding;
}
/**
* @param encoding the encoding to set
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* @return the codeInfokey
*/
public String getCodeInfokey() {
return codeInfokey;
}
/**
* @param codeInfokey the codeInfokey to set
*/
public void setCodeInfokey(String codeInfokey) {
this.codeInfokey = codeInfokey;
}
public abstract boolean supportWatchdog();
public abstract ExecuteWatchdog getWatchdog();
}
//=====================
// Test class
/**
* This file created at 2016年1月12日.
*
* Copyright (c) 2002-2016 Honey, Inc. All rights reserved.
*/
package com.honey.command;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.exec.ExecuteWatchdog;
import com.honey.proxy.helper.AbstractCommonExecs;
import com.honey.proxy.helper.ExecResult;
/**
* <code>{@link GbkCommonExecs}</code>
*
* windows开发环境测试
*
* @author Honwhy
*/
public class GbkCommonExecs extends AbstractCommonExecs{
/**
* @param bin
* @param arguments
*/
public GbkCommonExecs(String bin, List<String> arguments) {
super(bin, arguments);
}
/* (non-Javadoc)
* @see com.bingosoft.proxy.helper.AbstractCommonExecs#supportWatchdog()
*/
@Override
public boolean supportWatchdog() {
// TODO implement AbstractCommonExecs.supportWatchdog
return false;
}
/* (non-Javadoc)
* @see com.bingosoft.proxy.helper.AbstractCommonExecs#getWatchdog()
*/
@Override
public ExecuteWatchdog getWatchdog() {
// TODO implement AbstractCommonExecs.getWatchdog
return null;
}
public String getEncoding() {
return "GBK";
}
public static void main(String[] args) {
String bin = "ping";
String arg1 = "127.0.0.1";
List<String> arguments = new ArrayList<String>();
arguments.add(arg1);
AbstractCommonExecs executable = new GbkCommonExecs(bin, arguments);
ExecResult er = executable.exec();
System.out.println(er.getExitCode());
System.out.println(er.getStdout());
System.out.println(er.getStderr());
}
}
3.为什么执行GbkCommonExecs没有输出(可能死锁了)
4.如果把PipedInputStream和PipedOutputStream的方式换掉,换成ByteArrayOutputStream的方式,就能够正常输出,参考笔记代码的注释代码。
5.应该怎么使用PipedInputStream和PipedOutputStream使得我能够每行读取标准输出并做解析,解析到我需要的内容。
这个AbstractCommonExecs
并不能获得脚本的错误输出,比如创建一个文件夹两次,第二次应该会提示类似目录已存在的错误,但是封装后的代码只能看到apache common execs
的异常堆栈:
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
commons-exec 包中有 org.apache.commons.exec.LogOutputStream 类
可以通过继承该类实现一个实时输出的队列 读取阻塞队列里的内容来获取命令输出结果
Java管道流使用起来问题比较多,不太方便且控制不好容易出现IOException
PumpStreamHandler streamHandler = new PumpStreamHandler(CommandExecOutputStream);
public class CommandExecOutputStream extends LogOutputStream {
static Logger logger = LoggerFactory.getLogger(CommandExecOutputStream.class);
private BlockingQueue<String> queue;
public CommandExecOutputStream(){
}
public CommandExecOutputStream(BlockingQueue<String> queue){
this.queue = queue;
}
@Override
protected void processLine(String line, int level) {
try {
logger.debug("{}",line);
queue.put(line);
} catch (InterruptedException e) {
logger.error("命令执行过程输出InterruptedException",e);
}
}
}