반응형

최근 자바 어플리케이션에서 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

반응형

+ Recent posts