최근 자바 어플리케이션에서 hdfs파일을 local파일로 쓰는 외부 명령을 실행시켜야 하는 작업이 있었다.
Runtime 객체를 생성하고 exec 메소드를 이용하여 외부 명령을 실행시키는 프로세스를 생성하였다.
코드를 보면 알겠지만 command 명령에 파이프라인(|)이 사용되었다.
Runtime runtime = Runtime.getRuntime();
Process process = null;
String command = "hadoop fs -text /log/dmp_log/2017/09/19/dmp_log.*.1505786400000.gz | head -100"
process = runtime.exec(command);
이렇게 해서 동작을 시키니 100라인만 읽어와야하는데 해당 hdfs파일의 모든 로그를 읽어왔었다...
한참을 헤매다가 파이프라인(|)이 안먹는다는 생각이 들었고 찾아보니 문제가 있었다.
파이프라인(|)을 사용하는 것은 shell 실행 후 또 다른 프로세스로 실행하기 때문에 정상적으로 작동을 안한 것이다.
다음과 같이 해결을 하면 된다.
String commandHdfs = "hadoop fs -text /log/dmp_log/" + date + "/dmp_log.*." + unixTime + "000.gz | head -150";
String[] command = {
"/bin/sh",
"-c",
commandHdfs
};
[ stack overflow 참고 ]
https://stackoverflow.com/questions/5928225/how-to-make-pipes-work-with-runtime-exec
간단히 요약하자면, 자바 어플레케이션에서 exec로 실행하는 system command는 실제로 unix, linux의 shell을 불러와 명령을 실행시키는게 아니라고하네요.
그렇기 때문에 쉘의 기능(shell feature)인 pipeline (파이프라인)을 사용하기 위해서는 명시적으로 shell(/bin/sh)을 불러주고
해당 쉘 안에서 command를 실행시켜야 한다고 합니다.
더 정확한 원인을 알고 싶다면 참고부탁드려요
https://alvinalexander.com/java/java-exec-system-command-pipeline-pipe
'Programming > Java,Spring' 카테고리의 다른 글
[ Spring ] 스프링(Spring) @ControllerAdvice 예외처리시 우선순위? (0) | 2017.10.05 |
---|---|
[ JAVA ] 자바(java) 압축파일 확장자 확인하기(commons compress) (1) | 2017.10.05 |
[ spring ] java.lang.NoClassDefFoundError:org/springframework/data/cassandra/mapping/UserTypeResolver 에러 (0) | 2017.09.12 |
[ JAVA ] 자바(java) split이용시 주의사항 (0) | 2017.07.19 |
Process와 Thread 정리 (0) | 2017.05.25 |