import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
public class ShellTest {
String[] command = new String[]{"ls","-al"};
@Test
public void withProcessBuilder() throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
printStream(process);
}
@Test
public void withRunetime() throws IOException, InterruptedException {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(command);
printStream(process);
}
private void printStream(Process process) throws IOException, InterruptedException {
process.waitFor();
InputStream stream = process.getInputStream();
IOUtils.copy(stream, System.out);
IOUtils.closeQuietly(stream);
}
}
무한 대기 문제
public static void main(String[] args) throws IOException, InterruptedException{ Process pc = Runtime.getRuntime().exec("java"); InputStream input = pc.getInputStream(); IOUtils.copy(input, System.out); int exitCode = pc.waitFor(); System.out.println(exitCode); }
waitFor는 무한대기 될 수도 있다…
그런데 위의 코드를 Runtime.exec("javac")를 실행시키는 코드로 바꾸어보면, 이 호출은 영원히 끝나지 않게 됩니다.
When Runtime.exec() won’t : : javaworld에 올라온 고전이자 최고의 글
-
You cannot obtain an exit status from an external process until it has exited
-
You must immediately handle the input, output, and error streams from your spawned external process
-
You must use Runtime.exec() to execute programs
-
You cannot use Runtime.exec() like a command line Alvin Alexander의 글
-
Running system commands in Java applications : 스트림 처리 제대로 암함
-
http://alvinalexander.com/java/java-exec-processbuilder-process-1 : 개선판
-
http://alvinalexander.com/java/java-exec-processbuilder-process-2
-
http://alvinalexander.com/java/java-exec-processbuilder-process-3
-
분산처리 프레임워크 JPPF의 ProcessWrapper
-
Alvin Alexander가 Java exec - execute system processes with Java ProcessBuilder and Process 글에 공유한 소스
-
SystemCommandExecutor : shell 실행 전담 클래스
-
ThreadedStreamHandler : 스트림처리 클래스
-
ProcessBuilderExample : SystemCommandExecutor를 사용하는 예제
-
Apache-commons-exec의 PumpStreamHandler (Ant의 것과 패키지는 다르나 같은 코드)
-
Exec-maven-plugin의 ExecMojo (Apache-commons-exec를 활용) public class StreamConverter implements Runnable {
private StringBuilder message =null; private InputStream input = null; public StreamConverter(InputStream input){ this.input = input; this.message = new StringBuilder(); }
public void run() { BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line= null; try { while( (line = reader.readLine())!=null){ message.append(line); } } catch (IOException e) { throw new IllegalStateException("cann not read stream",e); } }
public StringBuilder getMessage() { return message; } }
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-exec</artifactId> <version>1.1</version> </dependency>